From c89cec2f0cf09e1cccb79e6884c52d0a375b525e Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Wed, 22 Jan 2025 08:18:08 +0000 Subject: [PATCH 01/26] fix(nrLDPC_coding): timers in DL encoding While timers were available for rate matching and interleaving in the new interface, these timers were not merged to rate matching and interleaving timers in nr_dlsch_coding. --- openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index d64c32059c..6d836fb386 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -309,6 +309,16 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, gNB->nrLDPC_coding_interface.nrLDPC_coding_encoder(&slot_parameters); + for (int dlsch_id=0; dlsch_idnum_pdsch_slot; dlsch_id++) { + nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[dlsch_id]; + for (int r = 0; r < TB_parameters->C; r++) { + nrLDPC_segment_encoding_parameters_t *segment_parameters = &TB_parameters->segments[r]; + merge_meas(dlsch_interleaving_stats, &segment_parameters->ts_interleave); + merge_meas(dlsch_rate_matching_stats, &segment_parameters->ts_rate_match); + // merge_meas(, &segment_parameters->ts_ldpc_encode); + } + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_OUT); return 0; } From 4384021938020c6dab9103fb641231d2b843b433 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Wed, 22 Jan 2025 08:24:16 +0000 Subject: [PATCH 02/26] fix(nrLDPC_coding): Apply clang-format to openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c --- openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 112 ++++++++------------ 1 file changed, 47 insertions(+), 65 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 6d836fb386..29ea38232c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -20,8 +20,8 @@ */ /*! \file PHY/NR_TRANSPORT/nr_dlsch_coding_slot.c -* \brief Top-level routines for implementing LDPC-coded (DLSCH) transport channels from 38-212, 15.2 -*/ + * \brief Top-level routines for implementing LDPC-coded (DLSCH) transport channels from 38-212, 15.2 + */ #include "PHY/defs_gNB.h" #include "PHY/CODING/coding_extern.h" @@ -39,17 +39,17 @@ #include #include -//#define DEBUG_DLSCH_CODING -//#define DEBUG_DLSCH_FREE 1 +// #define DEBUG_DLSCH_CODING +// #define DEBUG_DLSCH_FREE 1 void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARMS *frame_parms) { - int max_layers = (frame_parms->nb_antennas_txnb_antennas_tx : NR_MAX_NB_LAYERS; - uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*max_layers; + int max_layers = (frame_parms->nb_antennas_tx < NR_MAX_NB_LAYERS) ? frame_parms->nb_antennas_tx : NR_MAX_NB_LAYERS; + uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * max_layers; if (N_RB != 273) { - a_segments = a_segments*N_RB; - a_segments = a_segments/273 +1; + a_segments = a_segments * N_RB; + a_segments = a_segments / 273 + 1; } NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; @@ -70,16 +70,16 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARM NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB) { - int max_layers = (frame_parms->nb_antennas_txnb_antennas_tx : NR_MAX_NB_LAYERS; - uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*max_layers; //number of segments to be allocated + int max_layers = (frame_parms->nb_antennas_tx < NR_MAX_NB_LAYERS) ? frame_parms->nb_antennas_tx : NR_MAX_NB_LAYERS; + uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * max_layers; // number of segments to be allocated if (N_RB != 273) { - a_segments = a_segments*N_RB; - a_segments = a_segments/273 +1; + a_segments = a_segments * N_RB; + a_segments = a_segments / 273 + 1; } - LOG_D(PHY,"Allocating %d segments (MAX %d, N_PRB %d)\n",a_segments,MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER,N_RB); - uint32_t dlsch_bytes = a_segments*1056; // allocated bytes per segment + LOG_D(PHY, "Allocating %d segments (MAX %d, N_PRB %d)\n", a_segments, MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER, N_RB); + uint32_t dlsch_bytes = a_segments * 1056; // allocated bytes per segment NR_gNB_DLSCH_t dlsch; NR_DL_gNB_HARQ_t *harq = &dlsch.harq_process; @@ -88,7 +88,7 @@ NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB) AssertFatal(harq->b, "cannot allocate memory for harq->b\n"); bzero(harq->b, dlsch_bytes); - harq->c = (uint8_t **)malloc16(a_segments*sizeof(uint8_t *)); + harq->c = (uint8_t **)malloc16(a_segments * sizeof(uint8_t *)); for (int r = 0; r < a_segments; r++) { // account for filler in first segment and CRCs for multiple segment case // [hna] 8448 is the maximum CB size in NR @@ -103,7 +103,7 @@ NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB) AssertFatal(harq->f, "cannot allocate harq->f\n"); bzero(harq->f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); - return(dlsch); + return (dlsch); } int nr_dlsch_encoding(PHY_VARS_gNB *gNB, @@ -120,34 +120,30 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, time_stats_t *dlsch_interleaving_stats, time_stats_t *dlsch_segmentation_stats) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN); nrLDPC_TB_encoding_parameters_t TBs[msgTx->num_pdsch_slot]; memset(TBs, 0, sizeof(TBs)); - nrLDPC_slot_encoding_parameters_t slot_parameters = { - .frame = frame, - .slot = slot, - .nb_TBs = msgTx->num_pdsch_slot, - .threadPool = &gNB->threadPool, - .tinput = tinput, - .tprep = tprep, - .tparity = tparity, - .toutput = toutput, - .TBs = TBs - }; + nrLDPC_slot_encoding_parameters_t slot_parameters = {.frame = frame, + .slot = slot, + .nb_TBs = msgTx->num_pdsch_slot, + .threadPool = &gNB->threadPool, + .tinput = tinput, + .tprep = tprep, + .tparity = tparity, + .toutput = toutput, + .TBs = TBs}; int num_segments = 0; - for (int dlsch_id=0; dlsch_idnum_pdsch_slot; dlsch_id++) { - + for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) { NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id]; NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; - unsigned int crc=1; + unsigned int crc = 1; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; - uint32_t A = rel15->TBSize[0]<<3; - unsigned char *a=harq->pdu; + uint32_t A = rel15->TBSize[0] << 3; + unsigned char *a = harq->pdu; if (rel15->rnti != SI_RNTI) { ws_trace_t tmp = {.nr = true, .direction = DIRECTION_DOWNLINK, @@ -175,38 +171,30 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, phy_stats->dlsch_stats.current_Qm = rel15->qamModOrder[0]; } - int max_bytes = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers*1056; + int max_bytes = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * rel15->nrOfLayers * 1056; int B; if (A > NR_MAX_PDSCH_TBS) { // Add 24-bit crc (polynomial A) to payload - crc = crc24a(a,A)>>8; - a[A>>3] = ((uint8_t *)&crc)[2]; - a[1+(A>>3)] = ((uint8_t *)&crc)[1]; - a[2+(A>>3)] = ((uint8_t *)&crc)[0]; - //printf("CRC %x (A %d)\n",crc,A); - //printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]); + crc = crc24a(a, A) >> 8; + a[A >> 3] = ((uint8_t *)&crc)[2]; + a[1 + (A >> 3)] = ((uint8_t *)&crc)[1]; + a[2 + (A >> 3)] = ((uint8_t *)&crc)[0]; + // printf("CRC %x (A %d)\n",crc,A); + // printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]); B = A + 24; // harq->b = a; - AssertFatal((A / 8) + 4 <= max_bytes, - "A %d is too big (A/8+4 = %d > %d)\n", - A, - (A / 8) + 4, - max_bytes); + AssertFatal((A / 8) + 4 <= max_bytes, "A %d is too big (A/8+4 = %d > %d)\n", A, (A / 8) + 4, max_bytes); memcpy(harq->b, a, (A / 8) + 4); // why is this +4 if the CRC is only 3 bytes? } else { // Add 16-bit crc (polynomial A) to payload - crc = crc16(a,A)>>16; - a[A>>3] = ((uint8_t *)&crc)[1]; - a[1+(A>>3)] = ((uint8_t *)&crc)[0]; - //printf("CRC %x (A %d)\n",crc,A); - //printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]); + crc = crc16(a, A) >> 16; + a[A >> 3] = ((uint8_t *)&crc)[1]; + a[1 + (A >> 3)] = ((uint8_t *)&crc)[0]; + // printf("CRC %x (A %d)\n",crc,A); + // printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]); B = A + 16; // harq->b = a; - AssertFatal((A / 8) + 3 <= max_bytes, - "A %d is too big (A/8+3 = %d > %d)\n", - A, - (A / 8) + 3, - max_bytes); + AssertFatal((A / 8) + 3 <= max_bytes, "A %d is too big (A/8+3 = %d > %d)\n", A, (A / 8) + 3, max_bytes); memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc } @@ -228,12 +216,11 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, TB_parameters->BG); stop_meas(dlsch_segmentation_stats); - if (TB_parameters->C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers) { + if (TB_parameters->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * rel15->nrOfLayers) { LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", TB_parameters->C, B); - return(-1); + return (-1); } num_segments += TB_parameters->C; - } nrLDPC_segment_encoding_parameters_t segments[num_segments]; @@ -284,18 +271,13 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, for (int r = 0; r < TB_parameters->C; r++) { nrLDPC_segment_encoding_parameters_t *segment_parameters = &TB_parameters->segments[r]; segment_parameters->c = harq->c[r]; - segment_parameters->E = nr_get_E(TB_parameters->G, - TB_parameters->C, - TB_parameters->Qm, - rel15->nrOfLayers, - r); + segment_parameters->E = nr_get_E(TB_parameters->G, TB_parameters->C, TB_parameters->Qm, rel15->nrOfLayers, r); segment_parameters->output = &output[dlsch_offset + r_offset]; r_offset += segment_parameters->E; reset_meas(&segment_parameters->ts_interleave); reset_meas(&segment_parameters->ts_rate_match); reset_meas(&segment_parameters->ts_ldpc_encode); - } segments_offset += TB_parameters->C; @@ -309,7 +291,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, gNB->nrLDPC_coding_interface.nrLDPC_coding_encoder(&slot_parameters); - for (int dlsch_id=0; dlsch_idnum_pdsch_slot; dlsch_id++) { + for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) { nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[dlsch_id]; for (int r = 0; r < TB_parameters->C; r++) { nrLDPC_segment_encoding_parameters_t *segment_parameters = &TB_parameters->segments[r]; From a5215ba04799fcdf17da0104a8e045b9cf90546e Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Wed, 22 Jan 2025 08:24:52 +0000 Subject: [PATCH 03/26] fix(nrLDPC_coding): Apply clang-format to openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c --- openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 89 ++++++++----------- 1 file changed, 37 insertions(+), 52 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index c61898e9bb..667c7146b0 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -20,9 +20,8 @@ */ /*! \file PHY/NR_TRANSPORT/nr_ulsch_decoding_slot.c -* \brief Top-level routines for decoding LDPC (ULSCH) transport channels from 38.212, V15.4.0 2018-12 -*/ - + * \brief Top-level routines for decoding LDPC (ULSCH) transport channels from 38.212, V15.4.0 2018-12 + */ // [from gNB coding] #include "PHY/defs_gNB.h" @@ -41,27 +40,26 @@ #include "common/utils/LOG/vcd_signal_dumper.h" #include "common/utils/LOG/log.h" #include -//#define DEBUG_ULSCH_DECODING -//#define gNB_DEBUG_TRACE +// #define DEBUG_ULSCH_DECODING +// #define gNB_DEBUG_TRACE -#define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384 -//#define DEBUG_CRC +#define OAI_UL_LDPC_MAX_NUM_LLR 27000 // 26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384 +// #define DEBUG_CRC #ifdef DEBUG_CRC #define PRINT_CRC_CHECK(a) a #else #define PRINT_CRC_CHECK(a) #endif -//extern double cpuf; +// extern double cpuf; void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch, uint16_t N_RB_UL) { - - uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated + uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS; // number of segments to be allocated if (N_RB_UL != 273) { - a_segments = a_segments*N_RB_UL; - a_segments = a_segments/273 +1; + a_segments = a_segments * N_RB_UL; + a_segments = a_segments / 273 + 1; } if (ulsch->harq_process) { @@ -83,12 +81,11 @@ void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch, uint16_t N_RB_UL) NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL) { - - uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated + uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS; // number of segments to be allocated if (N_RB_UL != 273) { - a_segments = a_segments*N_RB_UL; - a_segments = a_segments/273 +1; + a_segments = a_segments * N_RB_UL; + a_segments = a_segments / 273 + 1; } uint32_t ulsch_bytes = a_segments * 1056; // allocated bytes per segment @@ -110,7 +107,7 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL) } harq->d_to_be_cleared = calloc(a_segments, sizeof(bool)); AssertFatal(harq->d_to_be_cleared != NULL, "out of memory\n"); - return(ulsch); + return (ulsch); } int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, @@ -121,18 +118,15 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, uint8_t *ULSCH_ids, int nb_pusch) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 1); nrLDPC_TB_decoding_parameters_t TBs[nb_pusch]; memset(TBs, 0, sizeof(TBs)); - nrLDPC_slot_decoding_parameters_t slot_parameters = { - .frame = frame, - .slot = nr_tti_rx, - .nb_TBs = nb_pusch, - .threadPool = &phy_vars_gNB->threadPool, - .TBs = TBs - }; + nrLDPC_slot_decoding_parameters_t slot_parameters = {.frame = frame, + .slot = nr_tti_rx, + .nb_TBs = nb_pusch, + .threadPool = &phy_vars_gNB->threadPool, + .TBs = TBs}; int max_num_segments = 0; @@ -154,17 +148,17 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, // The harq_pid is not unique among the active HARQ processes in the instance so we use ULSCH_id instead TB_parameters->harq_unique_pid = ULSCH_id; - + // ------------------------------------------------------------------ TB_parameters->nb_rb = pusch_pdu->rb_size; TB_parameters->Qm = pusch_pdu->qam_mod_order; TB_parameters->mcs = pusch_pdu->mcs_index; TB_parameters->nb_layers = pusch_pdu->nrOfLayers; // ------------------------------------------------------------------ - + TB_parameters->processedSegments = &harq_process->processedSegments; harq_process->TBS = pusch_pdu->pusch_data.tb_size; - + TB_parameters->BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph; TB_parameters->A = (harq_process->TBS) << 3; NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti); @@ -181,7 +175,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, stats->ulsch_stats.total_bytes_tx += harq_process->TBS; } } - + uint8_t harq_pid = ulsch->harq_pid; LOG_D(PHY, "ULSCH Decoding, harq_pid %d rnti %x TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, Coderate %f RV %d round %d new RX %d\n", @@ -197,7 +191,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, pusch_pdu->pusch_data.rv_index, harq_process->round, harq_process->harq_to_be_cleared); - + // [hna] Perform nr_segmenation with input and output set to NULL to calculate only (C, K, Z, F) nr_segmentation(NULL, NULL, @@ -211,40 +205,34 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, harq_process->K = TB_parameters->K; harq_process->Z = TB_parameters->Z; harq_process->F = TB_parameters->F; - + uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * TB_parameters->nb_layers; // number of segments to be allocated if (TB_parameters->C > a_segments) { LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, TB_parameters->A); - return(-1); + return (-1); } if (TB_parameters->nb_rb != 273) { - a_segments = a_segments*TB_parameters->nb_rb; - a_segments = a_segments/273 +1; + a_segments = a_segments * TB_parameters->nb_rb; + a_segments = a_segments / 273 + 1; } if (TB_parameters->C > a_segments) { - LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments); + LOG_E(PHY, "Illegal harq_process->C %d > %d\n", harq_process->C, a_segments); return -1; } max_num_segments = max(max_num_segments, TB_parameters->C); - + #ifdef DEBUG_ULSCH_DECODING printf("ulsch decoding nr segmentation Z %d\n", TB_parameters->Z); if (!frame % 100) - printf("K %d C %d Z %d \n", - TB_parameters->K, - TB_parameters->C, - TB_parameters->Z); - printf("Segmentation: C %d, K %d\n", - TB_parameters->C, - TB_parameters->K); + printf("K %d C %d Z %d \n", TB_parameters->K, TB_parameters->C, TB_parameters->Z); + printf("Segmentation: C %d, K %d\n", TB_parameters->C, TB_parameters->K); #endif - + TB_parameters->max_ldpc_iterations = ulsch->max_ldpc_iterations; TB_parameters->rv_index = pusch_pdu->pusch_data.rv_index; TB_parameters->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes; TB_parameters->abort_decode = &harq_process->abort_decode; set_abort(&harq_process->abort_decode, false); - } nrLDPC_segment_decoding_parameters_t segments[nb_pusch][max_num_segments]; @@ -267,11 +255,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, uint32_t r_offset = 0; for (int r = 0; r < TB_parameters->C; r++) { nrLDPC_segment_decoding_parameters_t *segment_parameters = &TB_parameters->segments[r]; - segment_parameters->E = nr_get_E(TB_parameters->G, - TB_parameters->C, - TB_parameters->Qm, - TB_parameters->nb_layers, - r); + segment_parameters->E = nr_get_E(TB_parameters->G, TB_parameters->C, TB_parameters->Qm, TB_parameters->nb_layers, r); segment_parameters->R = nr_get_R_ldpc_decoder(TB_parameters->rv_index, segment_parameters->E, TB_parameters->BG, @@ -296,7 +280,6 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, } harq_process->harq_to_be_cleared = false; } - } int ret_decoder = phy_vars_gNB->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters); @@ -314,7 +297,9 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, nrLDPC_segment_decoding_parameters_t nrLDPC_segment_decoding_parameters = TB_parameters.segments[r]; // Copy c to b in case of decoding success if (nrLDPC_segment_decoding_parameters.decodeSuccess) { - memcpy(harq_process->b + offset, harq_process->c[r], (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); + memcpy(harq_process->b + offset, + harq_process->c[r], + (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); } else { LOG_D(PHY, "uplink segment error %d/%d\n", r, harq_process->C); LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); From e6c802176d0a88cd1d3389447b2a02ad04d373da Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Wed, 22 Jan 2025 08:27:28 +0000 Subject: [PATCH 04/26] fix(nrLDPC_coding): Rename ldpc8blocks_coding_segment into ldpc8blocks The name ldpc8blocks_coding_segment was previously used to avoid any confusion with ldpc8blocks while both were coexisting. They are not anymore coexisting so it can now be shortened. --- .../nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c index adf9dd6624..7e1d272b6b 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c @@ -49,7 +49,7 @@ typedef struct ldpc8blocks_args_s { encoder_implemparams_t impp; } ldpc8blocks_args_t; -static void ldpc8blocks_coding_segment(void *p) +static void ldpc8blocks(void *p) { ldpc8blocks_args_t *args = (ldpc8blocks_args_t *)p; nrLDPC_TB_encoding_parameters_t *nrLDPC_TB_encoding_parameters = args->nrLDPC_TB_encoding_parameters; @@ -192,7 +192,7 @@ static int nrLDPC_prepare_TB_encoding(nrLDPC_slot_encoding_parameters_t *nrLDPC_ perJobImpp->impp = impp; perJobImpp->nrLDPC_TB_encoding_parameters = nrLDPC_TB_encoding_parameters; - task_t t = {.func = ldpc8blocks_coding_segment, .args = perJobImpp}; + task_t t = {.func = ldpc8blocks, .args = perJobImpp}; pushTpool(nrLDPC_slot_encoding_parameters->threadPool, t); } return n_seg; From aa2bebdeeec29f93219faf00e4007aad05da3676 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Fri, 24 Jan 2025 12:58:47 +0000 Subject: [PATCH 05/26] fix(ldpctest): Confusion in sizes The variable block_length had an ambiguous role and was used as both K and Kprime. This was leading to arrays with wrong sizes and functions with wrong arguments. Now there is not anymore block_length but K and Kprime. Kprime can be set with the command line argument `-l`. There was also some problems with array allocation for segments with length not divisible by 8. A proper sizing with `((size_in_bits + 7) & ~7) / 8` was used. A proper masking of the last byte containing payload bits was also added to keep filler bits to 0 after random initialization. --- openair1/PHY/CODING/TESTBENCH/ldpctest.c | 106 +++++++++++++---------- 1 file changed, 61 insertions(+), 45 deletions(-) diff --git a/openair1/PHY/CODING/TESTBENCH/ldpctest.c b/openair1/PHY/CODING/TESTBENCH/ldpctest.c index 71c2f1af27..83553fd578 100644 --- a/openair1/PHY/CODING/TESTBENCH/ldpctest.c +++ b/openair1/PHY/CODING/TESTBENCH/ldpctest.c @@ -102,7 +102,7 @@ one_measurement_t test_ldpc(short max_iterations, int denom_rate, double SNR, unsigned char qbits, - short block_length, + short Kprime, unsigned int ntrials, int n_segments) { @@ -119,9 +119,8 @@ one_measurement_t test_ldpc(short max_iterations, double sigma; sigma = 1.0/sqrt(2*SNR); cpu_meas_enabled = 1; - //short test_input[block_length]; uint8_t *test_input[MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS]; - uint8_t estimated_output[MAX_NUM_DLSCH_SEGMENTS][block_length]; + uint8_t estimated_output[MAX_NUM_DLSCH_SEGMENTS][Kprime]; memset(estimated_output, 0, sizeof(estimated_output)); uint8_t *channel_input[MAX_NUM_DLSCH_SEGMENTS]; uint8_t *channel_input_optim[MAX_NUM_DLSCH_SEGMENTS]; @@ -141,16 +140,6 @@ one_measurement_t test_ldpc(short max_iterations, int32_t n_iter = 0; - // generate input block - for(int j=0;j 3840) { + if (Kprime > 3840) { BG = 1; Kb = 22; nrows = 46; // parity check bits @@ -184,11 +168,11 @@ one_measurement_t test_ldpc(short max_iterations, BG = 2; nrows = 42; // parity check bits // ncols=10; // info bits - if (block_length > 640) + if (Kprime > 640) Kb = 10; - else if (block_length > 560) + else if (Kprime > 560) Kb = 9; - else if (block_length > 192) + else if (Kprime > 192) Kb = 8; else Kb = 6; @@ -240,18 +224,29 @@ one_measurement_t test_ldpc(short max_iterations, 22, 24, 26, 28, 30, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 88, 96, 104, 112, 120, 128, 144, 160, 176, 192, 208, 224, 240, 256, 288, 320, 352, 384}; for (i1 = 0; i1 < 51; i1++) { - if (lift_size[i1] >= (double)block_length / Kb) { + if (lift_size[i1] >= (double)Kprime / Kb) { Zc = lift_size[i1]; break; } } - printf("ldpc_test: codeword_length %d, n_segments %d, block_length %d, BG %d, Zc %d, Kb %d\n",n_segments *block_length, n_segments, block_length, BG, Zc, Kb); + // K: Segment size = number of columns in the parity check matrix * lifting size (number of columns of the square parity check sub-matrix) + int K = 0; + if (BG == 1) { + K = 22 * Zc; + } else if (BG == 2) { + K = 10 * Zc; + } else { + printf("Not supported: BG: %d\n", BG); + exit(1); + } + + printf("ldpc_test: codeword_length %d, n_segments %d, Kprime %d, BG %d, Zc %d, Kb %d\n", n_segments * K, n_segments, Kprime, BG, Zc, Kb); const int no_punctured_columns = - (int)((nrows - 2) * Zc + block_length - block_length * (1 / ((float)nom_rate / (float)denom_rate))) / Zc; + (int)((nrows - 2) * Zc + K - K * (1 / ((float)nom_rate / (float)denom_rate))) / Zc; // printf("puncture:%d\n",no_punctured_columns); const int removed_bit = - (nrows - no_punctured_columns - 2) * Zc + block_length - (int)(block_length / ((float)nom_rate / (float)denom_rate)); + (nrows - no_punctured_columns - 2) * Zc + K - (int)(K / ((float)nom_rate / (float)denom_rate)); printf("nrows: %d\n", nrows); printf("no_punctured_columns: %d\n", no_punctured_columns); @@ -259,7 +254,29 @@ one_measurement_t test_ldpc(short max_iterations, printf("To: %d\n", (Kb + nrows - no_punctured_columns) * Zc - removed_bit); printf("number of undecoded bits: %d\n", (Kb + nrows - no_punctured_columns - 2) * Zc - removed_bit); - encoder_implemparams_t impp = {.Zc = Zc, .Kb = Kb, .BG = BG, .K = block_length}; + // generate input block + for(int j=0;j> (i & 7); unsigned char inputbit = (test_input[j][i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments if (estoutputbit != inputbit) @@ -401,7 +420,7 @@ one_measurement_t test_ldpc(short max_iterations, configmodule_interface_t *uniqCfg = NULL; int main(int argc, char *argv[]) { - short block_length=8448; // decoder supports length: 1201 -> 1280, 2401 -> 2560 + short Kprime=8448; // default to check output inside ldpc, the NR version checks the outer CRC defined by 3GPP char *ldpc_version = "_optim8segmulti"; /* version of the ldpc decoder library to use (XXX suffix to use when loading libldpc_XXX.so */ @@ -452,7 +471,7 @@ int main(int argc, char *argv[]) break; case 'l': - block_length = atoi(optarg); + Kprime = atoi(optarg); break; case 'G': @@ -488,13 +507,13 @@ int main(int argc, char *argv[]) case 'h': default: printf("CURRENTLY SUPPORTED CODE RATES: \n"); - printf("BG1 (blocklength > 3840): 1/3, 2/3, 22/25 (8/9) \n"); - printf("BG2 (blocklength <= 3840): 1/5, 1/3, 2/3 \n\n"); + printf("BG1 (K' > 3840): 1/3, 2/3, 22/25 (8/9) \n"); + printf("BG2 (K' <= 3840): 1/5, 1/3, 2/3 \n\n"); printf("-h This message\n"); printf("-q Quantization bits, Default: 8\n"); printf("-r Nominator rate, (1, 2, 22), Default: 1\n"); printf("-d Denominator rate, (3, 5, 25), Default: 1\n"); - printf("-l Block length (l > 3840 -> BG1, rest BG2 ), Default: 8448\n"); + printf("-l Length of payload bits in a segment (K' in 38.212-5.2.2), [1, 8448], Default: 8448\n"); printf("-G give 1 to run cuda for LDPC, Default: 0\n"); printf("-n Number of simulation trials, Default: 1\n"); // printf("-M MCS2 for TB 2\n"); @@ -503,26 +522,23 @@ int main(int argc, char *argv[]) printf("-t SNR simulation step, Default: 0.1\n"); printf("-i Max decoder iterations, Default: 5\n"); printf("-u Set SNR per coded bit, Default: 0\n"); - printf("-v XXX Set ldpc shared library version. libldpc_XXX.so will be used \n"); + printf("-v _XXX Set ldpc shared library version. libldpc_XXX.so will be used \n"); exit(1); break; } } - //printf("the decoder supports BG2, Kb=10, Z=128 & 256\n"); - //printf(" range of blocklength: 1201 -> 1280, 2401 -> 2560\n"); - printf("block length %d: \n", block_length); + printf("block length %d: \n", Kprime); printf("n_trials %d: \n", n_trials); printf("SNR0 %f: \n", SNR0); load_LDPClib(ldpc_version, &ldpc_toCompare); load_LDPClib("_orig", &ldpc_orig); - //for (block_length=8;block_length<=MAX_BLOCK_LENGTH;block_length+=8) //find minimum value in all sets of lifting size Zc=0; char fname[200]; - sprintf(fname,"ldpctest_BG_%d_Zc_%d_rate_%d-%d_block_length_%d_maxit_%d.txt",BG,Zc,nom_rate,denom_rate,block_length, max_iterations); + sprintf(fname,"ldpctest_BG_%d_Zc_%d_rate_%d-%d_Kprime_%d_maxit_%d.txt", BG, Zc, nom_rate, denom_rate, Kprime, max_iterations); FILE *fd=fopen(fname,"w"); AssertFatal(fd!=NULL,"cannot open %s\n",fname); @@ -540,13 +556,13 @@ int main(int argc, char *argv[]) denom_rate, SNR_lin, // noise standard deviation qbits, - block_length, // block length bytes + Kprime, // block length bytes n_trials, n_segments); decoded_errors[i] = res.errors; dec_iter[i] = res.dec_iter; dec_iter[i].snr = SNR; - dec_iter[i].ber = (float)res.errors_bit / (float)n_trials / (float)block_length / (double)n_segments; + dec_iter[i].ber = (float)res.errors_bit / (float)n_trials / (float)Kprime / (double)n_segments; dec_iter[i].bler = (float)decoded_errors[i] / (float)n_trials; printf("SNR %f, BLER %f (%u/%d)\n", SNR, dec_iter[i].bler, decoded_errors[i], n_trials); printf("SNR %f, BER %f (%u/%d)\n", SNR, dec_iter[i].ber, decoded_errors[i], n_trials); @@ -571,7 +587,7 @@ int main(int argc, char *argv[]) "%f %f %f %f %f %f %f %f %f %f %f %f %d \n", SNR, (double)decoded_errors[i] / (double)n_trials, - (double)res.errors_bit / (double)n_trials / (double)block_length / (double)n_segments, + (double)res.errors_bit / (double)n_trials / (double)Kprime / (double)n_segments, res.errors_bit_uncoded / (double)n_trials / (double)n_segments, (double)res.time_optim.diff / res.time_optim.trials / 1000.0 / get_cpu_freq_GHz(), sqrt((double)res.time_optim.diff_square / res.time_optim.trials / pow(1000, 2) / pow(get_cpu_freq_GHz(), 2) From 430f0081eaf3f16a6c9df828255a961567399c20 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Fri, 24 Jan 2025 13:26:24 +0000 Subject: [PATCH 06/26] fix(ldpctest): apply clang-format to openair1/PHY/CODING/TESTBENCH/ldpctest.c --- openair1/PHY/CODING/TESTBENCH/ldpctest.c | 221 ++++++++++++----------- 1 file changed, 116 insertions(+), 105 deletions(-) diff --git a/openair1/PHY/CODING/TESTBENCH/ldpctest.c b/openair1/PHY/CODING/TESTBENCH/ldpctest.c index 83553fd578..6531a36a06 100644 --- a/openair1/PHY/CODING/TESTBENCH/ldpctest.c +++ b/openair1/PHY/CODING/TESTBENCH/ldpctest.c @@ -29,7 +29,7 @@ #include "common/config/config_userapi.h" #include "common/utils/load_module_shlib.h" #include "PHY/CODING/nrLDPC_extern.h" -//#include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h" +// #include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h" #include "openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.h" #include "openair1/PHY/defs_nr_common.h" #include "coding_unitary_defs.h" @@ -38,7 +38,7 @@ #define MAX_BLOCK_LENGTH 8448 #ifndef malloc16 -# define malloc16(x) memalign(32,x) +#define malloc16(x) memalign(32, x) #endif #define NR_LDPC_PROFILER_DETAIL @@ -46,10 +46,10 @@ ldpc_interface_t ldpc_orig, ldpc_toCompare; // 4-bit quantizer -int8_t quantize4bit(double D,double x) +int8_t quantize4bit(double D, double x) { double qxd; - qxd = floor(x/D); + qxd = floor(x / D); // printf("x=%f,qxd=%f\n",x,qxd); if (qxd <= -8) @@ -57,25 +57,25 @@ int8_t quantize4bit(double D,double x) else if (qxd > 7) qxd = 7; - return((int8_t)qxd); + return ((int8_t)qxd); } -int8_t quantize8bit(double D,double x) +int8_t quantize8bit(double D, double x) { double qxd; - //int8_t maxlev; - qxd = floor(x/D); + // int8_t maxlev; + qxd = floor(x / D); - //maxlev = 1<<(B-1); + // maxlev = 1<<(B-1); - //printf("x=%f,qxd=%f,maxlev=%d\n",x,qxd, maxlev); + // printf("x=%f,qxd=%f,maxlev=%d\n",x,qxd, maxlev); if (qxd <= -128) qxd = -128; else if (qxd >= 128) qxd = 127; - return((int8_t)qxd); + return ((int8_t)qxd); } typedef struct { @@ -109,32 +109,32 @@ one_measurement_t test_ldpc(short max_iterations, one_measurement_t ret = {0}; reset_meas(&ret.time_optim); reset_meas(&ret.time_decoder); - //clock initiate - //time_stats_t time,time_optim,tinput,tprep,tparity,toutput, time_decoder; - time_stats_t time, tinput,tprep,tparity,toutput; + // clock initiate + // time_stats_t time,time_optim,tinput,tprep,tparity,toutput, time_decoder; + time_stats_t time, tinput, tprep, tparity, toutput; double n_iter_mean = 0; double n_iter_std = 0; int n_iter_max = 0; double sigma; - sigma = 1.0/sqrt(2*SNR); + sigma = 1.0 / sqrt(2 * SNR); cpu_meas_enabled = 1; uint8_t *test_input[MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS]; uint8_t estimated_output[MAX_NUM_DLSCH_SEGMENTS][Kprime]; memset(estimated_output, 0, sizeof(estimated_output)); uint8_t *channel_input[MAX_NUM_DLSCH_SEGMENTS]; uint8_t *channel_input_optim[MAX_NUM_DLSCH_SEGMENTS]; - //double channel_output[68 * 384]; - double modulated_input[MAX_NUM_DLSCH_SEGMENTS][68 * 384] = { 0 }; - int8_t channel_output_fixed[MAX_NUM_DLSCH_SEGMENTS][68 * 384] = { 0 }; - short BG=0,nrows=0;//,ncols; + // double channel_output[68 * 384]; + double modulated_input[MAX_NUM_DLSCH_SEGMENTS][68 * 384] = {0}; + int8_t channel_output_fixed[MAX_NUM_DLSCH_SEGMENTS][68 * 384] = {0}; + short BG = 0, nrows = 0; //,ncols; int i1, Kb = 0; int R_ind = 0; - //int n_segments=1; + // int n_segments=1; int code_rate_vec[8] = {15, 13, 25, 12, 23, 34, 56, 89}; - //double code_rate_actual_vec[8] = {0.2, 0.33333, 0.4, 0.5, 0.66667, 0.73333, 0.81481, 0.88}; + // double code_rate_actual_vec[8] = {0.2, 0.33333, 0.4, 0.5, 0.66667, 0.73333, 0.81481, 0.88}; - t_nrLDPC_dec_params decParams[MAX_NUM_DLSCH_SEGMENTS]={0}; + t_nrLDPC_dec_params decParams[MAX_NUM_DLSCH_SEGMENTS] = {0}; t_nrLDPC_time_stats decoder_profiler = {0}; @@ -145,7 +145,7 @@ one_measurement_t test_ldpc(short max_iterations, reset_meas(&tprep); reset_meas(&tparity); reset_meas(&toutput); - //Reset Decoder profiles + // Reset Decoder profiles reset_meas(&decoder_profiler.llr2llrProcBuf); reset_meas(&decoder_profiler.llr2CnProcBuf); reset_meas(&decoder_profiler.cnProc); @@ -156,9 +156,9 @@ one_measurement_t test_ldpc(short max_iterations, reset_meas(&decoder_profiler.bn2cnProcBuf); reset_meas(&decoder_profiler.llrRes2llrOut); reset_meas(&decoder_profiler.llr2bit); - //reset_meas(&decoder_profiler.total); + // reset_meas(&decoder_profiler.total); - //determine number of bits in codeword + // determine number of bits in codeword if (Kprime > 3840) { BG = 1; Kb = 22; @@ -221,8 +221,8 @@ one_measurement_t test_ldpc(short max_iterations, // find minimum value in all sets of lifting size int Zc = 0; const short lift_size[51] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, - 22, 24, 26, 28, 30, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 88, - 96, 104, 112, 120, 128, 144, 160, 176, 192, 208, 224, 240, 256, 288, 320, 352, 384}; + 22, 24, 26, 28, 30, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 88, + 96, 104, 112, 120, 128, 144, 160, 176, 192, 208, 224, 240, 256, 288, 320, 352, 384}; for (i1 = 0; i1 < 51; i1++) { if (lift_size[i1] >= (double)Kprime / Kb) { Zc = lift_size[i1]; @@ -230,7 +230,8 @@ one_measurement_t test_ldpc(short max_iterations, } } - // K: Segment size = number of columns in the parity check matrix * lifting size (number of columns of the square parity check sub-matrix) + // K: Segment size = number of columns in the parity check matrix * lifting size (number of columns of the square parity check + // sub-matrix) int K = 0; if (BG == 1) { K = 22 * Zc; @@ -241,12 +242,16 @@ one_measurement_t test_ldpc(short max_iterations, exit(1); } - printf("ldpc_test: codeword_length %d, n_segments %d, Kprime %d, BG %d, Zc %d, Kb %d\n", n_segments * K, n_segments, Kprime, BG, Zc, Kb); - const int no_punctured_columns = - (int)((nrows - 2) * Zc + K - K * (1 / ((float)nom_rate / (float)denom_rate))) / Zc; + printf("ldpc_test: codeword_length %d, n_segments %d, Kprime %d, BG %d, Zc %d, Kb %d\n", + n_segments * K, + n_segments, + Kprime, + BG, + Zc, + Kb); + const int no_punctured_columns = (int)((nrows - 2) * Zc + K - K * (1 / ((float)nom_rate / (float)denom_rate))) / Zc; // printf("puncture:%d\n",no_punctured_columns); - const int removed_bit = - (nrows - no_punctured_columns - 2) * Zc + K - (int)(K / ((float)nom_rate / (float)denom_rate)); + const int removed_bit = (nrows - no_punctured_columns - 2) * Zc + K - (int)(K / ((float)nom_rate / (float)denom_rate)); printf("nrows: %d\n", nrows); printf("no_punctured_columns: %d\n", no_punctured_columns); @@ -255,7 +260,7 @@ one_measurement_t test_ldpc(short max_iterations, printf("number of undecoded bits: %d\n", (Kb + nrows - no_punctured_columns - 2) * Zc - removed_bit); // generate input block - for(int j=0;j> (i & 7); - unsigned char inputbit = (test_input[j][i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments - if (estoutputbit != inputbit) - ret.errors_bit++; + unsigned char estoutputbit = (estimated_output[j][i / 8] & (1 << (i & 7))) >> (i & 7); + unsigned char inputbit = (test_input[j][i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments + if (estoutputbit != inputbit) + ret.errors_bit++; } n_iter_mean += n_iter; n_iter_std += pow(n_iter - 1, 2); if (n_iter > n_iter_max) - n_iter_max = n_iter; + n_iter_max = n_iter; } // end segments @@ -383,7 +388,7 @@ one_measurement_t test_ldpc(short max_iterations, ret.dec_iter.n_iter_mean = n_iter_mean / (double)ntrials / (double)n_segments - 1; ret.dec_iter.n_iter_std = - sqrt(n_iter_std / (double)ntrials / (double)n_segments - pow(n_iter_mean / (double)ntrials / (double)n_segments - 1, 2)); + sqrt(n_iter_std / (double)ntrials / (double)n_segments - pow(n_iter_mean / (double)ntrials / (double)n_segments - 1, 2)); ret.dec_iter.n_iter_max = n_iter_max - 1; ret.errors_bit_uncoded = ret.errors_bit_uncoded / (double)((Kb + nrows - no_punctured_columns - 2) * Zc - removed_bit); @@ -394,24 +399,24 @@ one_measurement_t test_ldpc(short max_iterations, free(channel_input_optim[j]); } - print_meas(&time,"ldpc_encoder",NULL,NULL); + print_meas(&time, "ldpc_encoder", NULL, NULL); print_meas(&ret.time_optim, "ldpc_encoder_optim", NULL, NULL); - print_meas(&tinput,"ldpc_encoder_optim(input)",NULL,NULL); - print_meas(&tprep,"ldpc_encoder_optim(prep)",NULL,NULL); - print_meas(&tparity,"ldpc_encoder_optim(parity)",NULL,NULL); - print_meas(&toutput,"ldpc_encoder_optim(output)",NULL,NULL); + print_meas(&tinput, "ldpc_encoder_optim(input)", NULL, NULL); + print_meas(&tprep, "ldpc_encoder_optim(prep)", NULL, NULL); + print_meas(&tparity, "ldpc_encoder_optim(parity)", NULL, NULL); + print_meas(&toutput, "ldpc_encoder_optim(output)", NULL, NULL); printf("\n"); print_meas(&ret.time_decoder, "ldpc_decoder", NULL, NULL); - print_meas(&decoder_profiler.llr2llrProcBuf,"llr2llrProcBuf",NULL,NULL); - print_meas(&decoder_profiler.llr2CnProcBuf,"llr2CnProcBuf",NULL,NULL); - print_meas(&decoder_profiler.cnProc,"cnProc (per iteration)",NULL,NULL); - print_meas(&decoder_profiler.cnProcPc,"cnProcPc (per iteration)",NULL,NULL); - print_meas(&decoder_profiler.bnProc,"bnProc (per iteration)",NULL,NULL); - print_meas(&decoder_profiler.bnProcPc,"bnProcPc(per iteration)",NULL,NULL); - print_meas(&decoder_profiler.cn2bnProcBuf,"cn2bnProcBuf (per iteration)",NULL,NULL); - print_meas(&decoder_profiler.bn2cnProcBuf,"bn2cnProcBuf (per iteration)",NULL,NULL); - print_meas(&decoder_profiler.llrRes2llrOut,"llrRes2llrOut",NULL,NULL); - print_meas(&decoder_profiler.llr2bit,"llr2bit",NULL,NULL); + print_meas(&decoder_profiler.llr2llrProcBuf, "llr2llrProcBuf", NULL, NULL); + print_meas(&decoder_profiler.llr2CnProcBuf, "llr2CnProcBuf", NULL, NULL); + print_meas(&decoder_profiler.cnProc, "cnProc (per iteration)", NULL, NULL); + print_meas(&decoder_profiler.cnProcPc, "cnProcPc (per iteration)", NULL, NULL); + print_meas(&decoder_profiler.bnProc, "bnProc (per iteration)", NULL, NULL); + print_meas(&decoder_profiler.bnProcPc, "bnProcPc(per iteration)", NULL, NULL); + print_meas(&decoder_profiler.cn2bnProcBuf, "cn2bnProcBuf (per iteration)", NULL, NULL); + print_meas(&decoder_profiler.bn2cnProcBuf, "bn2cnProcBuf (per iteration)", NULL, NULL); + print_meas(&decoder_profiler.llrRes2llrOut, "llrRes2llrOut", NULL, NULL); + print_meas(&decoder_profiler.llr2bit, "llr2bit", NULL, NULL); printf("\n"); return ret; @@ -420,18 +425,18 @@ one_measurement_t test_ldpc(short max_iterations, configmodule_interface_t *uniqCfg = NULL; int main(int argc, char *argv[]) { - short Kprime=8448; + short Kprime = 8448; // default to check output inside ldpc, the NR version checks the outer CRC defined by 3GPP char *ldpc_version = "_optim8segmulti"; /* version of the ldpc decoder library to use (XXX suffix to use when loading libldpc_XXX.so */ - short max_iterations=5; - int n_segments=1; - //double rate=0.333; - - int nom_rate=1; - int denom_rate=3; - double SNR0=-2.0; - uint8_t qbits=8; + short max_iterations = 5; + int n_segments = 1; + // double rate=0.333; + + int nom_rate = 1; + int denom_rate = 3; + double SNR0 = -2.0; + uint8_t qbits = 8; unsigned int decoded_errors[10000]; // initiate the size of matrix equivalent to size of SNR int c, i = 0; @@ -439,7 +444,7 @@ int main(int argc, char *argv[]) double SNR_step = 0.1; randominit(0); - int test_uncoded= 0; + int test_uncoded = 0; n_iter_stats_t dec_iter[400] = {0}; short BG = 0, Zc; @@ -449,14 +454,13 @@ int main(int argc, char *argv[]) } logInit(); - while ((c = getopt (argc, argv, "--:O:q:r:s:S:l:G:n:d:i:t:u:hv:")) != -1) { - + while ((c = getopt(argc, argv, "--:O:q:r:s:S:l:G:n:d:i:t:u:hv:")) != -1) { /* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */ /* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */ if (c == 1 || c == '-' || c == 'O') continue; - printf("handling optarg %c\n",c); + printf("handling optarg %c\n", c); switch (c) { case 'q': qbits = atoi(optarg); @@ -473,9 +477,9 @@ int main(int argc, char *argv[]) case 'l': Kprime = atoi(optarg); break; - + case 'G': - ldpc_version="_cuda"; + ldpc_version = "_cuda"; break; case 'n': @@ -534,15 +538,17 @@ int main(int argc, char *argv[]) load_LDPClib(ldpc_version, &ldpc_toCompare); load_LDPClib("_orig", &ldpc_orig); - //find minimum value in all sets of lifting size - Zc=0; + // find minimum value in all sets of lifting size + Zc = 0; char fname[200]; - sprintf(fname,"ldpctest_BG_%d_Zc_%d_rate_%d-%d_Kprime_%d_maxit_%d.txt", BG, Zc, nom_rate, denom_rate, Kprime, max_iterations); - FILE *fd=fopen(fname,"w"); - AssertFatal(fd!=NULL,"cannot open %s\n",fname); + sprintf(fname, "ldpctest_BG_%d_Zc_%d_rate_%d-%d_Kprime_%d_maxit_%d.txt", BG, Zc, nom_rate, denom_rate, Kprime, max_iterations); + FILE *fd = fopen(fname, "w"); + AssertFatal(fd != NULL, "cannot open %s\n", fname); - fprintf(fd,"SNR BLER BER UNCODED_BER ENCODER_MEAN ENCODER_STD ENCODER_MAX DECODER_TIME_MEAN DECODER_TIME_STD DECODER_TIME_MAX DECODER_ITER_MEAN DECODER_ITER_STD DECODER_ITER_MAX\n"); + fprintf(fd, + "SNR BLER BER UNCODED_BER ENCODER_MEAN ENCODER_STD ENCODER_MAX DECODER_TIME_MEAN DECODER_TIME_STD DECODER_TIME_MAX " + "DECODER_ITER_MEAN DECODER_ITER_STD DECODER_ITER_MAX\n"); for (double SNR = SNR0; SNR < SNR0 + 20.0; SNR += SNR_step) { double SNR_lin; @@ -575,13 +581,18 @@ int main(int argc, char *argv[]) printf("SNR %f, Std iterations: %f\n", SNR, dec_iter[i].n_iter_std); printf("SNR %f, Max iterations: %d\n", SNR, dec_iter[i].n_iter_max); printf("\n"); - printf("Encoding time mean: %15.3f us\n",(double)res.time_optim.diff/res.time_optim.trials/1000.0/get_cpu_freq_GHz()); - printf("Encoding time std: %15.3f us\n",sqrt((double)res.time_optim.diff_square/res.time_optim.trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)res.time_optim.diff/res.time_optim.trials/1000.0/get_cpu_freq_GHz(),2))); - printf("Encoding time max: %15.3f us\n",(double)res.time_optim.max/1000.0/get_cpu_freq_GHz()); + printf("Encoding time mean: %15.3f us\n", (double)res.time_optim.diff / res.time_optim.trials / 1000.0 / get_cpu_freq_GHz()); + printf("Encoding time std: %15.3f us\n", + sqrt((double)res.time_optim.diff_square / res.time_optim.trials / pow(1000, 2) / pow(get_cpu_freq_GHz(), 2) + - pow((double)res.time_optim.diff / res.time_optim.trials / 1000.0 / get_cpu_freq_GHz(), 2))); + printf("Encoding time max: %15.3f us\n", (double)res.time_optim.max / 1000.0 / get_cpu_freq_GHz()); printf("\n"); - printf("Decoding time mean: %15.3f us\n",(double)res.time_decoder.diff/res.time_decoder.trials/1000.0/get_cpu_freq_GHz()); - printf("Decoding time std: %15.3f us\n",sqrt((double)res.time_decoder.diff_square/res.time_decoder.trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)res.time_decoder.diff/res.time_decoder.trials/1000.0/get_cpu_freq_GHz(),2))); - printf("Decoding time max: %15.3f us\n",(double)res.time_decoder.max/1000.0/get_cpu_freq_GHz()); + printf("Decoding time mean: %15.3f us\n", + (double)res.time_decoder.diff / res.time_decoder.trials / 1000.0 / get_cpu_freq_GHz()); + printf("Decoding time std: %15.3f us\n", + sqrt((double)res.time_decoder.diff_square / res.time_decoder.trials / pow(1000, 2) / pow(get_cpu_freq_GHz(), 2) + - pow((double)res.time_decoder.diff / res.time_decoder.trials / 1000.0 / get_cpu_freq_GHz(), 2))); + printf("Decoding time max: %15.3f us\n", (double)res.time_decoder.max / 1000.0 / get_cpu_freq_GHz()); fprintf(fd, "%f %f %f %f %f %f %f %f %f %f %f %f %d \n", @@ -601,7 +612,7 @@ int main(int argc, char *argv[]) dec_iter[i].n_iter_std, dec_iter[i].n_iter_max); - i=i+1; + i = i + 1; if (decoded_errors[i - 1] == 0) break; } @@ -614,5 +625,5 @@ int main(int argc, char *argv[]) loader_reset(); logTerm(); - return(0); + return (0); } From ad88beef1011a0b45e7d8864f86c5b698285878d Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Mon, 27 Jan 2025 14:40:14 +0000 Subject: [PATCH 07/26] fix(ldpctest): few improvements on top of clang-format changes --- openair1/PHY/CODING/TESTBENCH/ldpctest.c | 39 +++++++++++++----------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/openair1/PHY/CODING/TESTBENCH/ldpctest.c b/openair1/PHY/CODING/TESTBENCH/ldpctest.c index 6531a36a06..240274b197 100644 --- a/openair1/PHY/CODING/TESTBENCH/ldpctest.c +++ b/openair1/PHY/CODING/TESTBENCH/ldpctest.c @@ -565,6 +565,7 @@ int main(int argc, char *argv[]) Kprime, // block length bytes n_trials, n_segments); + decoded_errors[i] = res.errors; dec_iter[i] = res.dec_iter; dec_iter[i].snr = SNR; @@ -581,18 +582,22 @@ int main(int argc, char *argv[]) printf("SNR %f, Std iterations: %f\n", SNR, dec_iter[i].n_iter_std); printf("SNR %f, Max iterations: %d\n", SNR, dec_iter[i].n_iter_max); printf("\n"); - printf("Encoding time mean: %15.3f us\n", (double)res.time_optim.diff / res.time_optim.trials / 1000.0 / get_cpu_freq_GHz()); + + double cpu_freq = get_cpu_freq_GHz(); + time_stats_t *t_optim = &res.time_optim; + printf("Encoding time mean: %15.3f us\n", (double)t_optim->diff / t_optim->trials / 1000.0 / cpu_freq); printf("Encoding time std: %15.3f us\n", - sqrt((double)res.time_optim.diff_square / res.time_optim.trials / pow(1000, 2) / pow(get_cpu_freq_GHz(), 2) - - pow((double)res.time_optim.diff / res.time_optim.trials / 1000.0 / get_cpu_freq_GHz(), 2))); - printf("Encoding time max: %15.3f us\n", (double)res.time_optim.max / 1000.0 / get_cpu_freq_GHz()); + sqrt((double)t_optim->diff_square / t_optim->trials / pow(1000, 2) / pow(cpu_freq, 2) + - pow((double)t_optim->diff / t_optim->trials / 1000.0 / cpu_freq, 2))); + printf("Encoding time max: %15.3f us\n", (double)t_optim->max / 1000.0 / cpu_freq); printf("\n"); - printf("Decoding time mean: %15.3f us\n", - (double)res.time_decoder.diff / res.time_decoder.trials / 1000.0 / get_cpu_freq_GHz()); + + time_stats_t *t_decoder = &res.time_decoder; + printf("Decoding time mean: %15.3f us\n", (double)t_decoder->diff / t_decoder->trials / 1000.0 / cpu_freq); printf("Decoding time std: %15.3f us\n", - sqrt((double)res.time_decoder.diff_square / res.time_decoder.trials / pow(1000, 2) / pow(get_cpu_freq_GHz(), 2) - - pow((double)res.time_decoder.diff / res.time_decoder.trials / 1000.0 / get_cpu_freq_GHz(), 2))); - printf("Decoding time max: %15.3f us\n", (double)res.time_decoder.max / 1000.0 / get_cpu_freq_GHz()); + sqrt((double)t_decoder->diff_square / t_decoder->trials / pow(1000, 2) / pow(cpu_freq, 2) + - pow((double)t_decoder->diff / t_decoder->trials / 1000.0 / cpu_freq, 2))); + printf("Decoding time max: %15.3f us\n", (double)t_decoder->max / 1000.0 / cpu_freq); fprintf(fd, "%f %f %f %f %f %f %f %f %f %f %f %f %d \n", @@ -600,14 +605,14 @@ int main(int argc, char *argv[]) (double)decoded_errors[i] / (double)n_trials, (double)res.errors_bit / (double)n_trials / (double)Kprime / (double)n_segments, res.errors_bit_uncoded / (double)n_trials / (double)n_segments, - (double)res.time_optim.diff / res.time_optim.trials / 1000.0 / get_cpu_freq_GHz(), - sqrt((double)res.time_optim.diff_square / res.time_optim.trials / pow(1000, 2) / pow(get_cpu_freq_GHz(), 2) - - pow((double)res.time_optim.diff / res.time_optim.trials / 1000.0 / get_cpu_freq_GHz(), 2)), - (double)res.time_optim.max / 1000.0 / get_cpu_freq_GHz(), - (double)res.time_decoder.diff / res.time_decoder.trials / 1000.0 / get_cpu_freq_GHz(), - sqrt((double)res.time_decoder.diff_square / res.time_decoder.trials / pow(1000, 2) / pow(get_cpu_freq_GHz(), 2) - - pow((double)res.time_decoder.diff / res.time_decoder.trials / 1000.0 / get_cpu_freq_GHz(), 2)), - (double)res.time_decoder.max / 1000.0 / get_cpu_freq_GHz(), + (double)t_optim->diff / t_optim->trials / 1000.0 / cpu_freq, + sqrt((double)t_optim->diff_square / t_optim->trials / pow(1000, 2) / pow(cpu_freq, 2) + - pow((double)t_optim->diff / t_optim->trials / 1000.0 / cpu_freq, 2)), + (double)t_optim->max / 1000.0 / cpu_freq, + (double)t_decoder->diff / t_decoder->trials / 1000.0 / cpu_freq, + sqrt((double)t_decoder->diff_square / t_decoder->trials / pow(1000, 2) / pow(cpu_freq, 2) + - pow((double)t_decoder->diff / t_decoder->trials / 1000.0 / cpu_freq, 2)), + (double)t_decoder->max / 1000.0 / cpu_freq, dec_iter[i].n_iter_mean, dec_iter[i].n_iter_std, dec_iter[i].n_iter_max); From de4ef839569b881b7183a41d7d557747f244ce18 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Fri, 7 Feb 2025 14:34:31 +0000 Subject: [PATCH 08/26] feat(ldpctest): add BG2 test cases to CI --- cmake_targets/autotests/test_case_list.xml | 44 +++++++++++++++------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 32876634c0..132eb8cbe1 100755 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -66,16 +66,26 @@ - ldpc Test cases. (Test1: block length = 3872), - (Test2: block length = 4224), - (Test3: block length = 4576), - (Test4: block length = 4928), - (Test5: block length = 5280), - (Test6: block length = 5632), - (Test7: block length = 6336), - (Test8: block length = 7040), - (Test9: block length = 7744), - (Test10: block length = 8448) + ldpc Test cases. (Test1: block length = 3872, BG1), + (Test2: block length = 4224, BG1), + (Test3: block length = 4576, BG1), + (Test4: block length = 4928, BG1), + (Test5: block length = 5280, BG1), + (Test6: block length = 5632, BG1), + (Test7: block length = 6336, BG1), + (Test8: block length = 7040, BG1), + (Test9: block length = 7744, BG1), + (Test10: block length = 8448, BG1), + (Test11: block length = 1, BG2), + (Test12: block length = 100, BG2), + (Test13: block length = 193, BG2), + (Test14: block length = 500, BG2), + (Test15: block length = 561, BG2), + (Test16: block length = 600, BG2), + (Test17: block length = 641, BG2), + (Test18: block length = 2000, BG2), + (Test19: block length = 3000, BG2), + (Test20: block length = 3840, BG2) ldpctest -l3872 -s10 -n100 -l4224 -s10 -n100 @@ -87,9 +97,17 @@ -l7040 -s10 -n100 -l7744 -s10 -n100 -l8448 -s10 -n100 - -l561 -s10 -n1 - -l500 -s10 -n1 - test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 + -l1 -s10 -n100 + -l100 -s10 -n100 + -l193 -s10 -n100 + -l500 -s10 -n100 + -l561 -s10 -n100 + -l600 -s10 -n100 + -l641 -s10 -n100 + -l2000 -s10 -n100 + -l3000 -s10 -n100 + -l3840 -s10 -n100 + test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 test12 test13 test14 test15 test16 test17 test18 test19 test20 BLER 0.000000 segmentation fault|assertion|exiting|fatal|differ 3 From 9dada89cedac712f07fa58d72e33f2e819277eee Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Fri, 7 Feb 2025 14:48:42 +0000 Subject: [PATCH 09/26] feat(ldpctest): add CUDA ldpctest test cases to CI --- ci-scripts/xml_files/ldpc_gpu_test.xml | 165 ++++++++++++++++++++++++- 1 file changed, 164 insertions(+), 1 deletion(-) diff --git a/ci-scripts/xml_files/ldpc_gpu_test.xml b/ci-scripts/xml_files/ldpc_gpu_test.xml index f129d6bd2b..bee9035c8b 100644 --- a/ci-scripts/xml_files/ldpc_gpu_test.xml +++ b/ci-scripts/xml_files/ldpc_gpu_test.xml @@ -25,7 +25,10 @@ test-ldpc-gpu Test-ldpc-GPU tasks - 000002 000003 000004 000005 000006 000007 000008 000009 000010 000011 000012 000013 000014 000015 000016 000017 000018 000019 000020 000021 + + 000002 000003 000004 000005 000006 000007 000008 000009 000010 000011 000012 000013 000014 000015 000016 000017 000018 000019 000020 000021 + 000022 000023 000024 000025 000026 000027 000028 000029 000030 000031 000032 000033 000034 000035 000036 000037 000038 000039 000040 000041 + @@ -188,6 +191,166 @@ -l 8448 -s10 -n100 -G 1 + + Run_Physim + Run LDPC Test with CPU + true + ldpctest + -l 1 -s10 -n100 + + + + Run_Physim + Run LDPC Test with GPU + true + ldpctest + -l 1 -s10 -n100 -G 1 + + + + Run_Physim + Run LDPC Test with CPU + true + ldpctest + -l 100 -s10 -n100 + + + + Run_Physim + Run LDPC Test with GPU + true + ldpctest + -l 100 -s10 -n100 -G 1 + + + + Run_Physim + Run LDPC Test with CPU + true + ldpctest + -l 193 -s10 -n100 + + + + Run_Physim + Run LDPC Test with GPU + true + ldpctest + -l 193 -s10 -n100 -G 1 + + + + Run_Physim + Run LDPC Test with CPU + true + ldpctest + -l 500 -s10 -n100 + + + + Run_Physim + Run LDPC Test with GPU + true + ldpctest + -l 500 -s10 -n100 -G 1 + + + + Run_Physim + Run LDPC Test with CPU + true + ldpctest + -l 561 -s10 -n100 + + + + Run_Physim + Run LDPC Test with GPU + true + ldpctest + -l 561 -s10 -n100 -G 1 + + + + Run_Physim + Run LDPC Test with CPU + true + ldpctest + -l 600 -s10 -n100 + + + + Run_Physim + Run LDPC Test with GPU + true + ldpctest + -l 600 -s10 -n100 -G 1 + + + + Run_Physim + Run LDPC Test with CPU + true + ldpctest + -l 641 -s10 -n100 + + + + Run_Physim + Run LDPC Test with GPU + true + ldpctest + -l 641 -s10 -n100 -G 1 + + + + Run_Physim + Run LDPC Test with CPU + true + ldpctest + -l 2000 -s10 -n100 + + + + Run_Physim + Run LDPC Test with GPU + true + ldpctest + -l 2000 -s10 -n100 -G 1 + + + + Run_Physim + Run LDPC Test with CPU + true + ldpctest + -l 3000 -s10 -n100 + + + + Run_Physim + Run LDPC Test with GPU + true + ldpctest + -l 3000 -s10 -n100 -G 1 + + + + Run_Physim + Run LDPC Test with CPU + true + ldpctest + -l 3840 -s10 -n100 + + + + Run_Physim + Run LDPC Test with GPU + true + ldpctest + -l 3840 -s10 -n100 -G 1 + + From 4736f970551dd3483469bb7a9dba6345e880dd7c Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 14 Aug 2024 11:24:45 +0200 Subject: [PATCH 10/26] Indicate to NAS that the RRC connection has been established with a Connection Establishment Indication * ITTI from RRC to NAS * according to 5.3.1.3 of 3GPP TS 24.501 * set 5GMM mode to CONNECTED --- openair2/COMMON/rrc_messages_def.h | 1 + openair2/COMMON/rrc_messages_types.h | 1 + openair2/RRC/NR_UE/rrc_UE.c | 4 ++++ openair3/NAS/NR_UE/nr_nas_msg.c | 10 ++++++++++ 4 files changed, 16 insertions(+) diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h index cb4805ff5e..55f1708cc2 100644 --- a/openair2/COMMON/rrc_messages_def.h +++ b/openair2/COMMON/rrc_messages_def.h @@ -74,6 +74,7 @@ MESSAGE_DEF(NAS_CELL_SELECTION_IND, MESSAGE_PRIORITY_MED, cell_info_ind_t, nas_c MESSAGE_DEF(NAS_PAGING_IND, MESSAGE_PRIORITY_MED, paging_ind_t, nas_paging_ind) MESSAGE_DEF(NAS_CONN_ESTABLI_CNF, MESSAGE_PRIORITY_MED, nas_establish_cnf_t, nas_conn_establi_cnf) MESSAGE_DEF(NAS_CONN_RELEASE_IND, MESSAGE_PRIORITY_MED, nas_release_ind_t, nas_conn_release_ind) +MESSAGE_DEF(NR_NAS_CONN_ESTABLISH_IND, MESSAGE_PRIORITY_MED, nas_establish_ind_t, nr_nas_conn_establish_ind) MESSAGE_DEF(NR_NAS_CONN_RELEASE_IND, MESSAGE_PRIORITY_MED, NRNasConnReleaseInd, nr_nas_conn_release_ind) MESSAGE_DEF(NAS_UPLINK_DATA_CNF, MESSAGE_PRIORITY_MED, ul_info_transfer_cnf_t, nas_ul_data_cnf) MESSAGE_DEF(NAS_DOWNLINK_DATA_IND, MESSAGE_PRIORITY_MED, dl_info_transfer_ind_t, nas_dl_data_ind) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 5dc1e27f93..c7974a2746 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -84,6 +84,7 @@ #define NAS_PAGING_IND(mSGpTR) (mSGpTR)->ittiMsg.nas_paging_ind #define NAS_CONN_ESTABLI_CNF(mSGpTR) (mSGpTR)->ittiMsg.nas_conn_establi_cnf #define NAS_CONN_RELEASE_IND(mSGpTR) (mSGpTR)->ittiMsg.nas_conn_release_ind +#define NR_NAS_CONN_ESTABLISH_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_nas_conn_establish_ind #define NR_NAS_CONN_RELEASE_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_nas_conn_release_ind #define NAS_UPLINK_DATA_CNF(mSGpTR) (mSGpTR)->ittiMsg.nas_ul_data_cnf #define NAS_DOWNLINK_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nas_dl_data_ind diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 85adc82328..261ff2a60c 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1182,6 +1182,10 @@ static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc, // enter RRC_CONNECTED rrc->nrRrcState = RRC_STATE_CONNECTED_NR; + // Indicate to NAS that the RRC connection has been established (5.3.1.3 of 3GPP TS 24.501) + MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_NAS_CONN_ESTABLISH_IND); + itti_send_msg_to_task(TASK_NAS_NRUE, rrc->ue_id, msg_p); + // set the content of RRCSetupComplete message // TODO procedues described in 5.3.3.4 seems more complex than what we actualy do rrc_ue_generate_RRCSetupComplete(rrc, rrcSetup->rrc_TransactionIdentifier); diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 3c8da56280..803a4d6b55 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -1516,6 +1516,16 @@ void *nas_nrue(void *args_p) break; } + case NR_NAS_CONN_ESTABLISH_IND: { + nas->fiveGMM_mode = FGS_CONNECTED; + LOG_I(NAS, + "[UE %ld] Received %s: asCause %u\n", + nas->UE_id, + ITTI_MSG_NAME(msg_p), + NR_NAS_CONN_ESTABLISH_IND(msg_p).asCause); + break; + } + case NAS_CONN_ESTABLI_CNF: { LOG_I(NAS, "[UE %ld] Received %s: errCode %u, length %u\n", From ca869d8fd3001104fa8ea635428ea1b2691264f8 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 7 Feb 2025 07:44:35 +0100 Subject: [PATCH 11/26] Pass to RRC the 5G-S-TMSI extracted from NAS Registration Accept * NAS -> RRC: RRC receives an ITTI message with NAS 5GMM indication message containing the 5G-S-TMSI derived from NAS GUTI * 5G-S-TMSI is stored in the RRC instance and to be later encoded in the RRCSetup --- openair2/COMMON/as_message.h | 8 ++++++++ openair2/COMMON/rrc_messages_def.h | 1 + openair2/COMMON/rrc_messages_types.h | 1 + openair2/RRC/NR_UE/rrc_UE.c | 8 ++++++++ openair2/RRC/NR_UE/rrc_defs.h | 3 +++ openair3/NAS/NR_UE/nr_nas_msg.c | 14 ++++++++++++++ 6 files changed, 35 insertions(+) diff --git a/openair2/COMMON/as_message.h b/openair2/COMMON/as_message.h index 5a29d6881b..31d53d12fe 100644 --- a/openair2/COMMON/as_message.h +++ b/openair2/COMMON/as_message.h @@ -404,6 +404,13 @@ typedef struct nas_detach_req_s { bool wait_release; } nas_detach_req_t; +/** + * @brief 5GS mobility management information + * @ref clause 9.11.3 of 3GPP TS 24.501 + */ +typedef struct nas_5gmm_ind_s { + uint64_t fiveG_STMSI; +} nas_5gmm_ind_t; /* * -------------------------------------------------------------------------- * NAS information transfer @@ -578,6 +585,7 @@ typedef struct as_message_s { rab_establish_cnf_t rab_establish_cnf; rab_release_req_t rab_release_req; rab_release_ind_t rab_release_ind; + nas_5gmm_ind_t Nas5GMMInd; } __attribute__((__packed__)) msg; } as_message_t; diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h index 55f1708cc2..841c44d612 100644 --- a/openair2/COMMON/rrc_messages_def.h +++ b/openair2/COMMON/rrc_messages_def.h @@ -63,6 +63,7 @@ MESSAGE_DEF(NAS_CONN_ESTABLI_REQ, MESSAGE_PRIORITY_MED, nas_establish_req_t, nas MESSAGE_DEF(NAS_UPLINK_DATA_REQ, MESSAGE_PRIORITY_MED, ul_info_transfer_req_t, nas_ul_data_req) MESSAGE_DEF(NAS_DETACH_REQ, MESSAGE_PRIORITY_MED, nas_detach_req_t, nas_detach_req) MESSAGE_DEF(NAS_DEREGISTRATION_REQ, MESSAGE_PRIORITY_MED, nas_deregistration_req_t, nas_deregistration_req) +MESSAGE_DEF(NAS_5GMM_IND, MESSAGE_PRIORITY_MED, nas_5gmm_ind_t, nas_5gmm_ind) MESSAGE_DEF(NAS_RAB_ESTABLI_RSP, MESSAGE_PRIORITY_MED, rab_establish_rsp_t, nas_rab_est_rsp) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index c7974a2746..2446bbe4b3 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -76,6 +76,7 @@ #define NAS_UPLINK_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_ul_data_req #define NAS_DETACH_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_detach_req #define NAS_DEREGISTRATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_deregistration_req +#define NAS_5GMM_IND(mSGpTR) (mSGpTR)->ittiMsg.nas_5gmm_ind #define NAS_RAB_ESTABLI_RSP(mSGpTR) (mSGpTR)->ittiMsg.nas_rab_est_rsp diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 261ff2a60c..313347ed43 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -601,6 +601,8 @@ NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int nb_inst, int num_ant_tx) rrc->as_security_activated = false; rrc->detach_after_release = false; rrc->reconfig_after_reestab = false; + /* 5G-S-TMSI */ + rrc->fiveG_S_TMSI = UINT64_MAX; FILE *f = NULL; if (uecap_file) @@ -2098,6 +2100,12 @@ void *rrc_nrue(void *notUsed) break; } + case NAS_5GMM_IND: { + nas_5gmm_ind_t *req = &NAS_5GMM_IND(msg_p); + rrc->fiveG_S_TMSI = req->fiveG_STMSI; + break; + } + default: LOG_E(NR_RRC, "[UE %ld] Received unexpected message %s\n", rrc->ue_id, ITTI_MSG_NAME(msg_p)); break; diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index 29c03afd5f..ee46a343d7 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -239,6 +239,9 @@ typedef struct NR_UE_RRC_INST_s { Rrc_State_NR_t nrRrcState; // flag to identify 1st reconfiguration after reestablishment bool reconfig_after_reestab; + // 5G-S-TMSI + uint64_t fiveG_S_TMSI; + //Sidelink params NR_SL_PreconfigurationNR_r16_t *sl_preconfig; // NTN params diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 803a4d6b55..d259ea0dba 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -77,6 +77,8 @@ static nr_ue_nas_t nr_ue_nas[MAX_NAS_UE] = {0}; TYPE_DEF(NAS_SECURITY_INTEGRITY_PASSED, 4) \ TYPE_DEF(NAS_SECURITY_BAD_INPUT, 5) +const char *nr_release_cause_desc[] = {"RRC_CONNECTION_FAILURE", "RRC_RESUME_FAILURE", "OTHER"}; + typedef enum { FOREACH_STATE(TO_ENUM) } security_state_t; static const text_info_t security_state_info[] = {FOREACH_STATE(TO_TEXT)}; @@ -1365,6 +1367,15 @@ static void send_nas_detach_req(nr_ue_nas_t *nas, bool wait_release) itti_send_msg_to_task(TASK_RRC_NRUE, nas->UE_id, msg); } +static void send_nas_5gmm_ind(instance_t instance, const Guti5GSMobileIdentity_t *guti) +{ + MessageDef *msg = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_5GMM_IND); + nas_5gmm_ind_t *ind = &NAS_5GMM_IND(msg); + LOG_I(NR_RRC, "5G-GUTI: AMF pointer %u, AMF Set ID %u, 5G-TMSI %u \n", guti->amfpointer, guti->amfsetid, guti->tmsi); + ind->fiveG_STMSI = ((uint64_t)guti->amfsetid << 38) | ((uint64_t)guti->amfpointer << 32) | guti->tmsi; + itti_send_msg_to_task(TASK_RRC_NRUE, instance, msg); +} + static void request_default_pdusession(nr_ue_nas_t *nas) { MessageDef *message_p = itti_alloc_new_message(TASK_NAS_NRUE, nas->UE_id, NAS_PDU_SESSION_REQ); @@ -1439,6 +1450,9 @@ static void handle_registration_accept(nr_ue_nas_t *nas, const uint8_t *pdu_buff LOG_W(NAS, "no GUTI in registration accept\n"); } + if(nas->guti) + send_nas_5gmm_ind(nas->UE_id, nas->guti); + as_nas_info_t initialNasMsg = {0}; generateRegistrationComplete(nas, &initialNasMsg, NULL); if (initialNasMsg.length > 0) { From fb318e8e3fa8ca1b8cb08edbaef6a847c38cf255 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 7 Feb 2025 07:45:24 +0100 Subject: [PATCH 12/26] Cleanup commented out code in nas_nrue --- openair3/NAS/NR_UE/nr_nas_msg.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index d259ea0dba..8a51111cf3 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -1495,11 +1495,6 @@ void *nas_nrue(void *args_p) NAS_CELL_SELECTION_CNF(msg_p).errCode, NAS_CELL_SELECTION_CNF(msg_p).cellID, NAS_CELL_SELECTION_CNF(msg_p).tac); - // as_stmsi_t s_tmsi={0, 0}; - // as_nas_info_t nas_info; - // plmn_t plmnID={0, 0, 0, 0}; - // generateRegistrationRequest(&nas_info); - // nr_nas_itti_nas_establish_req(0, AS_TYPE_ORIGINATING_SIGNAL, s_tmsi, plmnID, nas_info.data, nas_info.length, 0); break; case NAS_CELL_SELECTION_IND: From 36a39b25a13dda3ee70525d59e9d882c5121bdc9 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 7 Feb 2025 07:46:04 +0100 Subject: [PATCH 13/26] Set 5GMM Mode to IDLE when receiving NR_NAS_CONN_RELEASE_IND > In N1 mode, upon indication from lower layers that the access stratum connection has been released, the UE shall enter 5GMM-IDLE mode and consider the N1 NAS signalling connection released (3GPP TS 24.501) --- openair3/NAS/NR_UE/nr_nas_msg.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 8a51111cf3..f78caf39f9 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -1565,8 +1565,12 @@ void *nas_nrue(void *args_p) break; } - case NR_NAS_CONN_RELEASE_IND: - LOG_I(NAS, "[UE %ld] Received %s: cause %u\n", nas->UE_id, ITTI_MSG_NAME(msg_p), NR_NAS_CONN_RELEASE_IND(msg_p).cause); + case NR_NAS_CONN_RELEASE_IND: { + LOG_I(NAS, "[UE %ld] Received %s: cause %s\n", + nas->UE_id, ITTI_MSG_NAME (msg_p), nr_release_cause_desc[NR_NAS_CONN_RELEASE_IND (msg_p).cause]); + /* In N1 mode, upon indication from lower layers that the access stratum connection has been released, + the UE shall enter 5GMM-IDLE mode and consider the N1 NAS signalling connection released (3GPP TS 24.501) */ + nas->fiveGMM_mode = FGS_IDLE; // TODO handle connection release if (nas->termination_procedure) { /* the following is not clean, but probably necessary: we need to give @@ -1577,7 +1581,7 @@ void *nas_nrue(void *args_p) itti_wait_tasks_unblock(); /* will unblock ITTI to stop nr-uesoftmodem */ } break; - + } case NAS_UPLINK_DATA_CNF: LOG_I(NAS, "[UE %ld] Received %s: UEid %u, errCode %u\n", From c6cc00633f155cc6506465b3b13a84cf37022372 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 7 Feb 2025 07:47:07 +0100 Subject: [PATCH 14/26] Rework handling of initial NAS message in RRCSetupComplete generation * use initialNasMsg to store nas messages buffer and length * buffer is dynamically allocated in generateRegistrationRequest, so do the same in NSA and free dynamic allocated data afterwards --- openair2/RRC/NR_UE/rrc_UE.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 313347ed43..9575fa1940 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1125,26 +1125,34 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, static void rrc_ue_generate_RRCSetupComplete(const NR_UE_RRC_INST_t *rrc, const uint8_t Transaction_id) { uint8_t buffer[100]; - const char *nas_msg; - int nas_msg_length; + as_nas_info_t initialNasMsg; if (IS_SA_MODE(get_softmodem_params())) { - as_nas_info_t initialNasMsg; nr_ue_nas_t *nas = get_ue_nas_info(rrc->ue_id); // Send Initial NAS message (Registration Request) before Security Mode control procedure generateRegistrationRequest(&initialNasMsg, nas, false); - nas_msg = (char *)initialNasMsg.nas_data; - nas_msg_length = initialNasMsg.length; + if (!initialNasMsg.nas_data) { + LOG_E(NR_RRC, "Failed to complete RRCSetup. NAS InitialUEMessage message not found.\n"); + return; + } } else { - nas_msg = nr_nas_attach_req_imsi_dummy_NSA_case; - nas_msg_length = sizeof(nr_nas_attach_req_imsi_dummy_NSA_case); + initialNasMsg.length = sizeof(nr_nas_attach_req_imsi_dummy_NSA_case); + initialNasMsg.nas_data = malloc_or_fail(initialNasMsg.length); + memcpy(initialNasMsg.nas_data, nr_nas_attach_req_imsi_dummy_NSA_case, initialNasMsg.length); } + // Encode RRCSetupComplete + int size = do_RRCSetupComplete(buffer, + sizeof(buffer), + Transaction_id, + rrc->selected_plmn_identity, + (const uint32_t)initialNasMsg.length, + (const char*)initialNasMsg.nas_data); + // Free dynamically allocated data (heap allocated in both SA and NSA) + free(initialNasMsg.nas_data); - int size = do_RRCSetupComplete(buffer, sizeof(buffer), Transaction_id, rrc->selected_plmn_identity, nas_msg_length, nas_msg); LOG_I(NR_RRC, "[UE %ld][RAPROC] Logical Channel UL-DCCH (SRB1), Generating RRCSetupComplete (bytes%d)\n", rrc->ue_id, size); int srb_id = 1; // RRC setup complete on SRB1 LOG_D(NR_RRC, "[RRC_UE %ld] PDCP_DATA_REQ/%d Bytes RRCSetupComplete ---> %d\n", rrc->ue_id, size, srb_id); - nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL); } From 27dccb8bce18e76150ca21702e78fc6ad2bcdbb7 Mon Sep 17 00:00:00 2001 From: ndomingues Date: Tue, 18 Feb 2025 09:51:40 +0000 Subject: [PATCH 15/26] Fix "Received Nack" log for Msg4/MsgB and minor improvement in RA logs --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 10 ++++++++-- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index d4b9c973ee..a8c434b62c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -2248,7 +2248,13 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, nr_clear_ra_proc(ra); } else { ra->ra_state = nrRA_WAIT_Msg4_MsgB_ACK; - LOG_I(NR_MAC,"UE %04x Generate msg4: feedback at %4d.%2d, payload %d bytes, next state WAIT_Msg4_ACK\n", ra->rnti, pucch->frame, pucch->ul_slot, harq->tb_size); + LOG_I(NR_MAC, + "UE %04x Generate %s: feedback at %4d.%2d, payload %d bytes, next state nrRA_WAIT_Msg4_MsgB_ACK\n", + ra->rnti, + ra_type_str, + pucch->frame, + pucch->ul_slot, + harq->tb_size); } } } @@ -2294,7 +2300,7 @@ static void nr_check_Msg4_MsgB_Ack(module_id_t module_id, int CC_id, frame_t fra remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); } } else { - LOG_I(NR_MAC, "(UE %04x) Received Nack in %s, preparing retransmission!\n", ra->rnti, nrra_text[ra->ra_state]); + LOG_I(NR_MAC, "(UE %04x) Received Nack in %s, preparing retransmission!\n", ra->rnti, ra_type_str); ra->ra_state = ra->ra_type == RA_4_STEP ? nrRA_Msg4 : nrRA_MsgB; } } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index a464611ec8..b9045e15a0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -126,7 +126,7 @@ typedef enum { } RA_gNB_state_t; static const char *const nrra_text[] = - {"IDLE", "Msg2", "WAIT_MsgA_PUSCH", "WAIT_Msg3", "Msg3_retransmission", "Msg3_dcch_dtch", "Msg4", "MsgB", "WAIT_Msg4_ACK"}; + {"IDLE", "Msg2", "WAIT_MsgA_PUSCH", "WAIT_Msg3", "Msg3_retransmission", "Msg4", "MsgB", "WAIT_Msg4_MsgB_ACK"}; typedef struct { int idx; From 1ce6167c45015ca9a7499300b5352499644f8d59 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 18 Feb 2025 11:19:59 +0100 Subject: [PATCH 16/26] free message after receiving it at MAC from RRC --- openair2/RRC/NR_UE/L2_interface_ue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index b6aa5f0463..7fd34ff91c 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -149,6 +149,7 @@ void process_msg_rcc_to_mac(MessageDef *msg) default: LOG_E(NR_MAC, "Unexpected msg from RRC: %d\n", ITTI_MSG_ID(msg)); } + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); } void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id) From cb72bd26f4afd381d0a2e11e7e08ce0602341aec Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 14 Feb 2025 11:00:51 +0100 Subject: [PATCH 17/26] do not send to L1 DCI PDU if there are no candidates --- openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index f6e3129ce9..77319d2013 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -39,9 +39,7 @@ #include "executables/softmodem-common.h" #include -void fill_dci_search_candidates(const NR_SearchSpace_t *ss, - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, - const uint32_t Y) +void fill_dci_search_candidates(const NR_SearchSpace_t *ss, fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, const uint32_t Y) { LOG_T(NR_MAC_DCI, "Filling search candidates for DCI\n"); @@ -320,6 +318,11 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, if (ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) Y = get_Y(ss, slot, rel15->rnti); fill_dci_search_candidates(ss, rel15, Y); + // not scheduling DCI reception if there are no candidates + if (rel15->number_of_candidates == 0) { + LOG_E(NR_MAC, "No candidates in this DCI, not scheduling it"); + return; + } #ifdef DEBUG_DCI for (int i = 0; i < rel15->num_dci_options; i++) { From e1d4ff11269e245e393c8461f761353cdf8806a5 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Wed, 19 Feb 2025 10:32:00 +0000 Subject: [PATCH 18/26] Upgrade SIMDe commit --- cmake_targets/tools/build_helper | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 5fee5ac48d..3fc1db7b56 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -674,8 +674,8 @@ install_simde_from_source(){ if [[ -v SIMDE_VERSION ]]; then git checkout -f $SIMDE_VERSION else - # At time of writing, last working commit for OAI: 1a09d3bc - git checkout 1a09d3bc9de47c4d9a5daa23eb753d5322748201 + # At time of writing, last working commit for OAI: c7f26b7 + git checkout c7f26b73ba8e874b95c2cec2b497826ad2188f68 fi # Showing which version is used git log -n1 From 48a307e172b508240a15e8ab5a7c60a24b2b5e1e Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 5 Jun 2024 11:24:13 +0200 Subject: [PATCH 19/26] Use 5G-S-TMSI in RRC connection setup procedures * Use the 5G-S-TMSI stored in RRC to be used as UE identity * Use 5G-S-TMSI part 1 in RRCSetupRequest encoding (TS 38.331 clause 5.3.3.3) * Set the ng-5G-S-TMSI-Value in RRCSetupComplete to ng-5G-S-TMSI-Part2 (5.3.3.4 of 3GPP TS 38.331) * current and only scenario: RRCSetup is received in response to an RRCSetupRequest --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 52 ++++++++++++++++++++++++----- openair2/RRC/NR/MESSAGES/asn1_msg.h | 4 ++- openair2/RRC/NR_UE/rrc_UE.c | 6 +++- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index b66625e6b2..e3df557d3d 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -765,7 +765,7 @@ int do_RRCReconfiguration(const gNB_RRC_UE_t *UE, return((enc_rval.encoded+7)/8); } -int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv) +int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv, uint64_t fiveG_S_TMSI) { NR_UL_CCCH_Message_t ul_ccch_msg = {0}; ul_ccch_msg.message.present = NR_UL_CCCH_MessageType_PR_c1; @@ -773,24 +773,34 @@ int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv) c1->present = NR_UL_CCCH_MessageType__c1_PR_rrcSetupRequest; asn1cCalloc(c1->choice.rrcSetupRequest, rrcSetupRequest); - if (1) { + if (fiveG_S_TMSI == UINT64_MAX) { + /* set the ue-Identity to a random value */ rrcSetupRequest->rrcSetupRequest.ue_Identity.present = NR_InitialUE_Identity_PR_randomValue; BIT_STRING_t *str = &rrcSetupRequest->rrcSetupRequest.ue_Identity.choice.randomValue; str->size = 5; str->bits_unused = 1; - str->buf = CALLOC(1, str->size); + str->buf = calloc_or_fail(str->size, sizeof(str->buf[0])); str->buf[0] = rv[0]; str->buf[1] = rv[1]; str->buf[2] = rv[2]; str->buf[3] = rv[3]; str->buf[4] = rv[4] & 0xfe; } else { + uint64_t fiveG_S_TMSI_part1 = fiveG_S_TMSI & ((1ULL << 39) - 1); + /** set the ue-Identity to ng-5G-S-TMSI-Part1 + * ng-5G-S-TMSI-Part1: the rightmost 39 bits of 5G-S-TMSI + * BIT STRING (SIZE (39)) - 3GPP TS 38.331 */ + LOG_D(NR_RRC, "5G-S-TMSI: %lu, set the ue-Identity to ng-5G-S-TMSI-Part1 %lu\n", fiveG_S_TMSI, fiveG_S_TMSI_part1); rrcSetupRequest->rrcSetupRequest.ue_Identity.present = NR_InitialUE_Identity_PR_ng_5G_S_TMSI_Part1; BIT_STRING_t *str = &rrcSetupRequest->rrcSetupRequest.ue_Identity.choice.ng_5G_S_TMSI_Part1; - str->size = 1; - str->bits_unused = 0; - str->buf = CALLOC(1, str->size); - str->buf[0] = 0x12; + str->size = 5; + str->bits_unused = 1; + str->buf = calloc_or_fail(str->size, sizeof(str->buf[0])); + str->buf[0] = (fiveG_S_TMSI_part1 >> 31) & 0xff; + str->buf[1] = (fiveG_S_TMSI_part1 >> 23) & 0xff; + str->buf[2] = (fiveG_S_TMSI_part1 >> 15) & 0xff; + str->buf[3] = (fiveG_S_TMSI_part1 >> 7) & 0xff; + str->buf[4] = (fiveG_S_TMSI_part1 << 1) & 0xff; } rrcSetupRequest->rrcSetupRequest.establishmentCause = NR_EstablishmentCause_mo_Signalling; //EstablishmentCause_mo_Data; @@ -872,6 +882,8 @@ int do_RRCSetupComplete(uint8_t *buffer, size_t buffer_size, const uint8_t Transaction_id, uint8_t sel_plmn_id, + bool is_rrc_connection_setup, + uint64_t fiveG_s_tmsi, const int dedicatedInfoNASLength, const char *dedicatedInfoNAS) { @@ -887,7 +899,31 @@ int do_RRCSetupComplete(uint8_t *buffer, NR_RRCSetupComplete_IEs_t *ies = RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete; ies->selectedPLMN_Identity = sel_plmn_id; ies->registeredAMF = NULL; - ies->ng_5G_S_TMSI_Value = NULL; + /* RRCSetup is received in response to an RRCSetupRequest + * set the ng-5G-S-TMSI-Value to ng-5G-S-TMSI-Part2 + * i.e. the leftmost 9 bits of 5G-S-TMSI (5.3.3.4 of 3GPP TS 38.331) */ + if (fiveG_s_tmsi != UINT64_MAX) { + if (is_rrc_connection_setup) { + ies->ng_5G_S_TMSI_Value = calloc_or_fail(1, sizeof(*ies->ng_5G_S_TMSI_Value)); + ies->ng_5G_S_TMSI_Value->present = NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value_PR_ng_5G_S_TMSI_Part2; + BIT_STRING_t *str = &ies->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI_Part2; + str->size = 2; + str->bits_unused = 7; + str->buf = calloc_or_fail(str->size, sizeof(str->buf[0])); + uint16_t fiveG_s_tmsi_part2 = (fiveG_s_tmsi >> 39) & ((1ULL << 9) - 1); + str->buf[0] = (fiveG_s_tmsi_part2 >> (8 - str->bits_unused)) & 0xFF; + str->buf[1] = (fiveG_s_tmsi_part2 << str->bits_unused) & 0xFF; + LOG_D(NR_RRC, "5G-S-TMSI part 2 %d in RRCSetupComplete (5G-S-TMSI %ld)\n", fiveG_s_tmsi_part2, fiveG_s_tmsi); + } else { + ies->ng_5G_S_TMSI_Value = CALLOC(1, sizeof(struct NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value)); + ies->ng_5G_S_TMSI_Value->present = NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value_PR_ng_5G_S_TMSI; + FIVEG_S_TMSI_TO_BIT_STRING(fiveG_s_tmsi, &ies->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI); + LOG_D(NR_RRC, "5G-S-TMSI %lu in RRCSetupComplete\n", fiveG_s_tmsi); + } + } else { + LOG_D(NR_RRC, "5G-S-TMSI is not available!\n"); + ies->ng_5G_S_TMSI_Value = NULL; + } memset(&ies->dedicatedNAS_Message,0,sizeof(OCTET_STRING_t)); OCTET_STRING_fromBuf(&ies->dedicatedNAS_Message, dedicatedInfoNAS, dedicatedInfoNASLength); diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index d7642ca663..a6c5e25aec 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -119,12 +119,14 @@ int do_RRCSetupComplete(uint8_t *buffer, size_t buffer_size, const uint8_t Transaction_id, uint8_t sel_plmn_id, + bool is_rrc_connection_setup, + uint64_t fiveG_S_TMSI, const int dedicatedInfoNASLength, const char *dedicatedInfoNAS); int do_NR_HandoverPreparationInformation(const uint8_t *uecap_buf, int uecap_buf_size, uint8_t *buf, int buf_size); -int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv); +int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv, uint64_t fiveG_S_TMSI_part1); int do_NR_RRCReconfigurationComplete_for_nsa(uint8_t *buffer, size_t buffer_size, NR_RRC_TransactionIdentifier_t Transaction_id); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 9575fa1940..6b8a12e4cc 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -276,7 +276,7 @@ static void nr_rrc_ue_prepare_RRCSetupRequest(NR_UE_RRC_INST_t *rrc) } uint8_t buf[1024]; - int len = do_RRCSetupRequest(buf, sizeof(buf), rv); + int len = do_RRCSetupRequest(buf, sizeof(buf), rv, rrc->fiveG_S_TMSI); nr_rlc_srb_recv_sdu(rrc->ue_id, 0, buf, len); } @@ -1140,13 +1140,17 @@ static void rrc_ue_generate_RRCSetupComplete(const NR_UE_RRC_INST_t *rrc, const initialNasMsg.nas_data = malloc_or_fail(initialNasMsg.length); memcpy(initialNasMsg.nas_data, nr_nas_attach_req_imsi_dummy_NSA_case, initialNasMsg.length); } + // Encode RRCSetupComplete int size = do_RRCSetupComplete(buffer, sizeof(buffer), Transaction_id, rrc->selected_plmn_identity, + rrc->ra_trigger == RRC_CONNECTION_SETUP, + rrc->fiveG_S_TMSI, (const uint32_t)initialNasMsg.length, (const char*)initialNasMsg.nas_data); + // Free dynamically allocated data (heap allocated in both SA and NSA) free(initialNasMsg.nas_data); From 89ca89ea4b9bc52c7612f5b251aa8673c479b56e Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 22 Jul 2024 16:06:29 +0200 Subject: [PATCH 20/26] Address integrity failure after UE reconnects from RRC IDLE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After a new connection from RRC IDLE, an integrity failure occurs. This commit is addressing this issue to pass the integrity check. * Reset ciphering and integrity algorithms when going into RRC IDLE * Use uplink NAS COUNT in Registration Request for initial KgNB derivation * Temporarily deriving UP protection keys in Registration Request * Note: AS SMC handling should be done according to 33.501 ยง6.8.1.1.2.2 --- openair2/RRC/NR_UE/rrc_UE.c | 2 ++ openair3/NAS/NR_UE/nr_nas_msg.c | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 6b8a12e4cc..f61ce49494 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -2562,6 +2562,8 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, // discard the keys (only kgnb is stored) memset(rrc->kgnb, 0, sizeof(rrc->kgnb)); + rrc->integrityProtAlgorithm = 0; + rrc->cipheringAlgorithm = 0; // release all radio resources, including release of the RLC entity, // the MAC configuration and the associated PDCP entity diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index f78caf39f9..64a541aa78 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -663,6 +663,12 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas, nasmessagecontainercontents->length = mm_msg_encode(&full_mm, nasmessagecontainercontents->value, size_nct); size += (nasmessagecontainercontents->length + 2); rr->presencemask |= REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT; + // Workaround to pass integrity in RRC_IDLE + uint8_t *kamf = nas->security.kamf; + uint8_t *kgnb = nas->security.kgnb; + derive_kgnb(kamf, nas->security.nas_count_ul, kgnb); + int nas_itti_kgnb_refresh_req(instance_t instance, const uint8_t kgnb[32]); + nas_itti_kgnb_refresh_req(nas->UE_id, nas->security.kgnb); } // Allocate buffer (including NAS message container size) initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data)); From 82fbb6bb0417675bd4be2286d978ab9f82620f88 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Mon, 27 Jan 2025 14:09:32 +0100 Subject: [PATCH 21/26] Remove unused noise_power_dB field in rfsimulator_state_t --- radio/rfsimulator/simulator.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index 262cb87deb..14be663d49 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -177,7 +177,6 @@ typedef struct { double chan_pathloss; double chan_forgetfact; uint64_t chan_offset; - float noise_power_dB; void *telnetcmd_qid; poll_telnetcmdq_func_t poll_telnetcmdq; int wait_timeout; @@ -456,7 +455,7 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, t->chan_forgetfact, // forgetting_factor t->chan_offset, // propagation delay in samples t->chan_pathloss, - t->noise_power_dB); // path_loss in dB + 0); // noise_power set_channeldesc_owner(newmodel, RFSIMU_MODULEID); set_channeldesc_name(newmodel,modelname); random_channel(newmodel,false); From 2fb541a68ef788c104f92faec5dab397c221a634 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Mon, 27 Jan 2025 17:39:19 +0100 Subject: [PATCH 22/26] Add option to use global noise power for all RX channels in RFSimulator Added new command line option to channelmod: noise_power_dBFS. This options allows the user to configure noise power in dBFS added instead of the per-channel value. This makes it so noise is not accumulated per channel reaching higher than expected values. The dBFS unit allows easy configuration. The gNB by default uses -36 dBFS setting. To reach 3dB SNR one should set the noise_power_dBFS value to -39. To configure using command line use --channelmod.noise_power_dBFS -50. Using this setting the gNB and nrUE connect without issue. --- .../TOOLS/DOC/channel_simulation.md | 1 + openair1/SIMULATION/TOOLS/random_channel.c | 5 +++ openair1/SIMULATION/TOOLS/sim.h | 6 ++++ radio/rfsimulator/apply_channelmod.c | 13 +++---- radio/rfsimulator/rfsimulator.h | 6 ++-- radio/rfsimulator/simulator.c | 34 +++++++++++++++++-- 6 files changed, 54 insertions(+), 11 deletions(-) diff --git a/openair1/SIMULATION/TOOLS/DOC/channel_simulation.md b/openair1/SIMULATION/TOOLS/DOC/channel_simulation.md index 070ee61ca0..30cc68e662 100644 --- a/openair1/SIMULATION/TOOLS/DOC/channel_simulation.md +++ b/openair1/SIMULATION/TOOLS/DOC/channel_simulation.md @@ -142,6 +142,7 @@ Channel simulation parameters can also be specified on the command line by using |:--- |:---- |:---- |:----| |`modellist` |char string |`DefaultChannelList`|select and load the `modellist` from the config file.| |`max_chan` |integer |10 |set the maximum number of channel models that can be defined in the system. Must be greater than the number of model definitions in the model list loaded at init time.| +|`noise_power_dBFS` |integer |0 |Noise power in dBFS. If set, noise per channel is not applied. To achieve positive SNR use values below the default gNB/nrUE amp backoff value (-36dBFS)| Example usage: ```bash diff --git a/openair1/SIMULATION/TOOLS/random_channel.c b/openair1/SIMULATION/TOOLS/random_channel.c index 4c715498a8..b9ae9e3fff 100644 --- a/openair1/SIMULATION/TOOLS/random_channel.c +++ b/openair1/SIMULATION/TOOLS/random_channel.c @@ -73,6 +73,7 @@ static telnetshell_vardef_t channelmod_vardef[] = {{"", 0, 0, NULL}}; static unsigned int max_chan; static channel_desc_t **defined_channels; static char *modellist_name; +static int noise_power_dBFS = INVALID_DBFS_VALUE; void fill_channel_desc(channel_desc_t *chan_desc, uint8_t nb_tx, @@ -2365,6 +2366,10 @@ int load_channellist(uint8_t nb_tx, uint8_t nb_rx, double sampling_rate, uint64_ return channel_list.numelt; } /* load_channelist */ +int get_noise_power_dBFS(void) { + return noise_power_dBFS; +} + #ifdef RANDOM_CHANNEL_MAIN #define sampling_rate 5.0 #define Td 2.0 diff --git a/openair1/SIMULATION/TOOLS/sim.h b/openair1/SIMULATION/TOOLS/sim.h index 8297d9c365..d6b20a9eb9 100644 --- a/openair1/SIMULATION/TOOLS/sim.h +++ b/openair1/SIMULATION/TOOLS/sim.h @@ -278,10 +278,15 @@ typedef enum { #define CHANNELMOD_MODELLIST_PARANAME "modellist" #define CHANNELMOD_HELP_MODELLIST " channel list name in config file describing the model type and its parameters\n" +#define CHANNELMOD_HELP_NOISE_POWER \ + "Noise power in dBFS. If set, noise per channel is not applied. To achieve positive SNR use values below -36dBFS\n" + +#define INVALID_DBFS_VALUE 100 // clang-format off #define CHANNELMOD_PARAMS_DESC { \ {"max_chan", "Max number of runtime models", 0, .uptr=&max_chan, .defintval=10, TYPE_UINT, 0}, \ {CHANNELMOD_MODELLIST_PARANAME, CHANNELMOD_HELP_MODELLIST, 0, .strptr=&modellist_name, .defstrval="DefaultChannelList", TYPE_STRING, 0}, \ + {"noise_power_dBFS", CHANNELMOD_HELP_NOISE_POWER, 0, .iptr=&noise_power_dBFS, .defintval=INVALID_DBFS_VALUE, TYPE_INT, 0 },\ } // clang-format on @@ -585,5 +590,6 @@ void do_DL_sig(sim_t *sim, int CC_id); void do_UL_sig(sim_t *sim, uint16_t subframe, uint8_t abstraction_flag, LTE_DL_FRAME_PARMS *frame_parms, uint32_t frame, int ru_id, uint8_t CC_id, int NB_UEs); +int get_noise_power_dBFS(void); #endif diff --git a/radio/rfsimulator/apply_channelmod.c b/radio/rfsimulator/apply_channelmod.c index cb8e75abdf..60d3afbe83 100644 --- a/radio/rfsimulator/apply_channelmod.c +++ b/radio/rfsimulator/apply_channelmod.c @@ -42,12 +42,13 @@ legacy: we regenerate each sub frame in UL, and each frame only in DL */ void rxAddInput(const c16_t *input_sig, - c16_t *after_channel_sig, + cf_t *after_channel_sig, int rxAnt, channel_desc_t *channelDesc, int nbSamples, uint64_t TS, - uint32_t CirSize) + uint32_t CirSize, + bool add_noise) { if ((channelDesc->sat_height > 0) && (channelDesc->enable_dynamic_delay || channelDesc->enable_dynamic_Doppler)) { // model for transparent satellite on circular orbit /* assumptions: @@ -127,12 +128,12 @@ void rxAddInput(const c16_t *input_sig, const double pathLossLinear = pow(10,channelDesc->path_loss_dB/20.0); // Energy in one sample to calibrate input noise // the normalized OAI value seems to be 256 as average amplitude (numerical amplification = 1) - const double noise_per_sample = pow(10,channelDesc->noise_power_dB/10.0) * 256; + const double noise_per_sample = add_noise ? pow(10,channelDesc->noise_power_dB/10.0) * 256 : 0; const uint64_t dd = channelDesc->channel_offset; const int nbTx=channelDesc->nb_tx; for (int i=0; iDoppler_phase_cur[rxAnt] += channelDesc->Doppler_phase_inc; } - out_ptr->r = lround(rx_tmp.r*pathLossLinear + noise_per_sample*gaussZiggurat(0.0,1.0)); - out_ptr->i = lround(rx_tmp.i*pathLossLinear + noise_per_sample*gaussZiggurat(0.0,1.0)); + out_ptr->r += rx_tmp.r * pathLossLinear + noise_per_sample * gaussZiggurat(0.0, 1.0); + out_ptr->i += rx_tmp.i * pathLossLinear + noise_per_sample * gaussZiggurat(0.0, 1.0); out_ptr++; } diff --git a/radio/rfsimulator/rfsimulator.h b/radio/rfsimulator/rfsimulator.h index 068250a149..11a57193ca 100644 --- a/radio/rfsimulator/rfsimulator.h +++ b/radio/rfsimulator/rfsimulator.h @@ -23,13 +23,15 @@ #ifndef __RFSIMULATOR_H #define __RFSIMULATOR_H +#include void rxAddInput( const c16_t *input_sig, - c16_t *after_channel_sig, + cf_t *after_channel_sig, int rxAnt, channel_desc_t *channelDesc, int nbSamples, uint64_t TS, - uint32_t CirSize + uint32_t CirSize, + bool apply_noise ); #endif diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index 14be663d49..ecf278ffd9 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -1006,7 +1006,9 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest // Clear the output buffer for (int a=0; abuf[sock]; @@ -1024,12 +1026,18 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest for (int a=0; achannel_model != NULL ) { // apply a channel model - rxAddInput(ptr->circularBuf, (c16_t *) samplesVoid[a], + if (num_chanmod_channels == 0) { + memset(temp_array, 0, sizeof(temp_array)); + } + num_chanmod_channels++; + rxAddInput(ptr->circularBuf, + temp_array[a], a, ptr->channel_model, nsamps, t->nextRxTstamp, - CirSize); + CirSize, + apply_noise_per_channel); } else { // no channel modeling int nbAnt_tx = ptr->th.nbAnt; // number of Tx antennas @@ -1063,6 +1071,26 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest } // end for a (number of rx antennas) } } + if (apply_noise_per_channel && num_chanmod_channels > 0) { + // Noise is already applied through the channel model + for (int a = 0; a < nbAnt; a++) { + sample_t *out = (sample_t *)samplesVoid[a]; + for (int i = 0; i < nsamps; i++) { + out[i].r += lroundf(temp_array[a][i].r); + out[i].i += lroundf(temp_array[a][i].i); + } + } + } else if (num_chanmod_channels > 0) { + // Apply noise from global setting + int16_t noise_power = (int16_t)(32767.0 / powf(10.0, .05 * -get_noise_power_dBFS())); + for (int a = 0; a < nbAnt; a++) { + sample_t *out = (sample_t *)samplesVoid[a]; + for (int i = 0; i < nsamps; i++) { + out[i].r += lroundf(temp_array[a][i].r + noise_power * gaussZiggurat(0.0, 1.0)); + out[i].i += lroundf(temp_array[a][i].i + noise_power * gaussZiggurat(0.0, 1.0)); + } + } + } *ptimestamp = t->nextRxTstamp; // return the time of the first sample t->nextRxTstamp+=nsamps; From c6ed26fca3dc6d4db1d596c2734a85aba4067552 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Wed, 19 Feb 2025 11:30:47 +0100 Subject: [PATCH 23/26] Add a metric for rfsimulator channel emulator performance Add a print and method to calculate rfsimulators channel emulation performance. The counter unit is Megasample/second (Msps). --- radio/rfsimulator/simulator.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index ecf278ffd9..c733f4c8a2 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -1003,6 +1003,11 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest } while (have_to_wait); } + + struct timespec start_time; + int ret = clock_gettime(CLOCK_REALTIME, &start_time); + AssertFatal(ret == 0, "clock_gettime() failed: errno %d, %s\n", errno, strerror(errno)); + // Clear the output buffer for (int a=0; asample_rate / 1e6); + } + *ptimestamp = t->nextRxTstamp; // return the time of the first sample t->nextRxTstamp+=nsamps; LOG_D(HW, From 66d8cf0f13cbe42c0fbbf801419f825d99eafb7e Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 19 Feb 2025 18:28:04 +0100 Subject: [PATCH 24/26] update of timing test thresholds to reflect current values --- ci-scripts/datalog_rt_stats.100.2x2.yaml | 14 +++++++------- ci-scripts/datalog_rt_stats.1x1.60.yaml | 16 ++++++++-------- ci-scripts/datalog_rt_stats.60.2x2.yaml | 14 +++++++------- ci-scripts/datalog_rt_stats.default.yaml | 14 +++++++------- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/ci-scripts/datalog_rt_stats.100.2x2.yaml b/ci-scripts/datalog_rt_stats.100.2x2.yaml index c54fb13018..7b5c8cbbeb 100644 --- a/ci-scripts/datalog_rt_stats.100.2x2.yaml +++ b/ci-scripts/datalog_rt_stats.100.2x2.yaml @@ -9,14 +9,14 @@ ColNames : Ref : feprx : 150.0 feptx_prec : 0.0 - feptx_ofdm : 65.0 - feptx_total : 177.0 - L1 Tx processing : 700.0 - DLSCH encoding : 226.0 - L1 Rx processing : 640.0 - PUSCH inner-receiver : 400.0 + feptx_ofdm : 60.0 + feptx_total : 150.0 + L1 Tx processing : 530.0 + DLSCH encoding : 220.0 + L1 Rx processing : 530.0 + PUSCH inner-receiver : 360.0 Schedule Response : 3.0 - DL & UL scheduling timing : 15.0 + DL & UL scheduling timing : 17.0 UL Indication : 3.0 Slot Indication : 17.0 DeviationThreshold : diff --git a/ci-scripts/datalog_rt_stats.1x1.60.yaml b/ci-scripts/datalog_rt_stats.1x1.60.yaml index f2cd345737..acd8251525 100644 --- a/ci-scripts/datalog_rt_stats.1x1.60.yaml +++ b/ci-scripts/datalog_rt_stats.1x1.60.yaml @@ -7,16 +7,16 @@ ColNames : - Average; Max; Count - Average vs Reference Deviation (Reference Value; Acceptability Deviation Threshold) Ref : - feprx : 46.0 + feprx : 40.0 feptx_prec : 15.0 - feptx_ofdm : 35.0 - feptx_total : 50.0 - L1 Tx processing : 260.0 - DLSCH encoding : 160.0 - L1 Rx processing : 420.0 - PUSCH inner-receiver : 170.0 + feptx_ofdm : 30.0 + feptx_total : 45.0 + L1 Tx processing : 205.0 + DLSCH encoding : 140.0 + L1 Rx processing : 345.0 + PUSCH inner-receiver : 150.0 Schedule Response : 3.0 - DL & UL scheduling timing : 8.0 + DL & UL scheduling timing : 7.0 UL Indication : 3.0 Slot Indication : 8.0 DeviationThreshold : diff --git a/ci-scripts/datalog_rt_stats.60.2x2.yaml b/ci-scripts/datalog_rt_stats.60.2x2.yaml index 66ab367e7c..a196695c4b 100644 --- a/ci-scripts/datalog_rt_stats.60.2x2.yaml +++ b/ci-scripts/datalog_rt_stats.60.2x2.yaml @@ -7,18 +7,18 @@ ColNames : - Average; Max; Count - Average vs Reference Deviation (Reference Value; Acceptability Deviation Threshold) Ref : - feprx : 84.0 + feprx : 75.0 feptx_prec : 14.0 - feptx_ofdm : 35.0 - feptx_total : 100.0 - L1 Tx processing : 400.0 - DLSCH encoding : 177.0 + feptx_ofdm : 30.0 + feptx_total : 80.0 + L1 Tx processing : 315.0 + DLSCH encoding : 155.0 L1 Rx processing : 345.0 - PUSCH inner-receiver : 200.0 + PUSCH inner-receiver : 155.0 Schedule Response : 3.0 DL & UL scheduling timing : 13.0 UL Indication : 3.0 - Slot Indication : 15.0 + Slot Indication : 12.0 DeviationThreshold : feprx : 0.25 feptx_prec : 0.25 diff --git a/ci-scripts/datalog_rt_stats.default.yaml b/ci-scripts/datalog_rt_stats.default.yaml index 1b83aed783..045768829c 100644 --- a/ci-scripts/datalog_rt_stats.default.yaml +++ b/ci-scripts/datalog_rt_stats.default.yaml @@ -7,17 +7,17 @@ ColNames : - Average; Max; Count - Average vs Reference Deviation (Reference Value; Acceptability Deviation Threshold) Ref : - feprx : 43.0 + feprx : 40.0 feptx_prec : 13.0 - feptx_ofdm : 33.0 - feptx_total : 50.0 - L1 Tx processing : 200.0 + feptx_ofdm : 30.0 + feptx_total : 45.0 + L1 Tx processing : 160.0 DLSCH encoding : 100.0 - L1 Rx processing : 330.0 - PUSCH inner-receiver : 120.0 + L1 Rx processing : 290.0 + PUSCH inner-receiver : 115.0 Schedule Response : 3.0 DL & UL scheduling timing : 6.0 - UL Indication : 3.0 + UL Indication : 2.0 Slot Indication : 7.0 DeviationThreshold : feprx : 0.25 From 5f2f907d53f11c73876bc27cade37551897083f8 Mon Sep 17 00:00:00 2001 From: Sagar Arora Date: Thu, 20 Feb 2025 08:31:50 +0100 Subject: [PATCH 25/26] chore(ci): change image rentention from 4weeks to 3weeks Signed-off-by: Sagar Arora --- ci-scripts/cls_cluster.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index a98dbf390d..7293e252a1 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -315,9 +315,9 @@ class Cluster: # delete old images by Sagar Arora : # 1. retrieve all images and their timestamp - # 2. awk retrieves those whose timestamp is older than 4 weeks + # 2. awk retrieves those whose timestamp is older than 3 weeks # 3. issue delete command on corresponding istags (the images are dangling and will be cleaned by the registry) - delete_cmd = "oc get istag -o go-template --template '{{range .items}}{{.metadata.name}} {{.metadata.creationTimestamp}}{{\"\\n\"}}{{end}}' | awk '$2 <= \"'$(date -d '-4weeks' -Ins --utc | sed 's/+0000/Z/')'\" { print $1 }' | xargs --no-run-if-empty oc delete istag" + delete_cmd = "oc get istag -o go-template --template '{{range .items}}{{.metadata.name}} {{.metadata.creationTimestamp}}{{\"\\n\"}}{{end}}' | awk '$2 <= \"'$(date -d '-3weeks' -Ins --utc | sed 's/+0000/Z/')'\" { print $1 }' | xargs --no-run-if-empty oc delete istag" response = self.cmd.run(delete_cmd) logging.debug(f"deleted images:\n{response.stdout}") From 2cc3f3bcac432d185a28f7cb51949c81f2f4b65d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 21 Feb 2025 07:42:45 +0100 Subject: [PATCH 26/26] Fix: write NSSAI info of F1AP Cell Info struct During refactoring, the previously implemented NSSAI field of the cell info structure was not written to F1AP ASN.1 structures anymore; eq_f1ap_cell_info() also conveniently omitted the corresponding equality check. Add this back so the CU can correctly receive the NSSAI in case of F1 split operation. Fixes: f278b008375d ("Add encoding/decoding library for F1AP Setup Request (Interface Management) ") --- openair2/F1AP/lib/f1ap_interface_management.c | 27 +++++++++++++++++++ openair2/F1AP/lib/f1ap_lib_common.c | 5 ++++ 2 files changed, 32 insertions(+) diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c index 08f324a618..4d8c4fcccf 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.c +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -404,6 +404,31 @@ static int read_slice_info(const F1AP_ServedPLMNs_Item_t *plmn, nssai_t *nssai, return ssl->list.count; } +static F1AP_ProtocolExtensionContainer_10696P34_t *write_slice_info(int num_ssi, const nssai_t *nssai) +{ + if (num_ssi == 0) + return NULL; + + F1AP_ProtocolExtensionContainer_10696P34_t *p = calloc_or_fail(1, sizeof(*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; + + for (int s = 0; s < num_ssi; s++) { + asn1cSequenceAdd(slice_support_list->list, F1AP_SliceSupportItem_t, slice); + const nssai_t *n = &nssai[s]; + INT8_TO_OCTET_STRING(n->sst, &slice->sNSSAI.sST); + if (n->sd != 0xffffff) { + asn1cCalloc(slice->sNSSAI.sD, tmp); + INT24_TO_OCTET_STRING(n->sd, tmp); + } + } + + return p; +} + /** * @brief F1AP Setup Request memory management */ @@ -468,6 +493,8 @@ static F1AP_Served_Cell_Information_t encode_served_cell_info(const f1ap_served_ asn1cSequenceAdd(scell_info.servedPLMNs.list, F1AP_ServedPLMNs_Item_t, servedPLMN_item); // PLMN Identity (M) MCC_MNC_TO_PLMNID(c->plmn.mcc, c->plmn.mnc, c->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity); + // NSSAIs (O) + servedPLMN_item->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)write_slice_info(c->num_ssi, c->nssai); // NR-Mode-Info (M) F1AP_NR_Mode_Info_t *nR_Mode_Info = &scell_info.nR_Mode_Info; if (c->mode == F1AP_MODE_FDD) { // FDD Info diff --git a/openair2/F1AP/lib/f1ap_lib_common.c b/openair2/F1AP/lib/f1ap_lib_common.c index c49a87c57c..3673fa3cc7 100644 --- a/openair2/F1AP/lib/f1ap_lib_common.c +++ b/openair2/F1AP/lib/f1ap_lib_common.c @@ -57,6 +57,11 @@ bool eq_f1ap_cell_info(const f1ap_served_cell_info_t *a, const f1ap_served_cell_ return false; if (a->tac) _F1_EQ_CHECK_INT(*a->tac, *b->tac); + _F1_EQ_CHECK_INT(a->num_ssi, b->num_ssi); + for (int i = 0; i < a->num_ssi; ++i) { + _F1_EQ_CHECK_INT(a->nssai[i].sst, b->nssai[i].sst); + _F1_EQ_CHECK_INT(a->nssai[i].sd, b->nssai[i].sd); + } _F1_EQ_CHECK_INT(a->mode, b->mode); if (a->mode == F1AP_MODE_TDD) { /* TDD */