From b5aad5956cee78bfd5d2bb7ead5e38ff1874217b Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Wed, 3 Dec 2025 15:06:31 +0100 Subject: [PATCH 1/8] vrtsim: rewrite sample history Limit sample history to 256 samples and copy it into each channel modelling task instead of relying on globally available buffer. This simplifies the code and addressing into the saved samples buffer as well as enabling further optimizations without sacrificing thread safety. --- radio/vrtsim/vrtsim.c | 55 ++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c index 9e678a5305..01589797d0 100644 --- a/radio/vrtsim/vrtsim.c +++ b/radio/vrtsim/vrtsim.c @@ -54,7 +54,7 @@ typedef enum { ROLE_SERVER = 1, ROLE_CLIENT } role; #define MAX_NUM_ANTENNAS_TX 4 -#define MAX_CHANNEL_LENGTH (1 << 20) +#define SAVED_SAMPLES_LEN 256 #define ROLE_CLIENT_STRING "client" #define ROLE_SERVER_STRING "server" @@ -125,9 +125,6 @@ typedef struct { int client_num_rx_antennas; } vrtsim_state_t; -// Sample history for channel impulse response -static c16_t saved_samples[MAX_NUM_ANTENNAS_TX][MAX_CHANNEL_LENGTH] __attribute__((aligned(32))) = {0}; - static void histogram_add(histogram_t *histogram, double diff) { histogram->num_samples++; @@ -375,6 +372,7 @@ typedef struct { int nbAnt; int flags; int aarx; + c16_t saved_samples[MAX_NUM_ANTENNAS_TX][SAVED_SAMPLES_LEN]; } channel_modelling_args_t; static void perform_channel_modelling(void *arg) @@ -418,14 +416,13 @@ static void perform_channel_modelling(void *arg) } for (int aatx = 0; aatx < nb_tx_ant; aatx++) { - c16_t *previous_samples = saved_samples[aatx]; for (int i = 0; i < nsamps; i++) { cf_t *impulse_response = channel_impulse_response_p[aatx]; for (int l = 0; l < channel_desc->channel_length; l++) { int idx = i - l; // TODO: Use AVX2 for this c16_t tx_input = idx >= 0 ? input_samples[aatx][idx] - : previous_samples[(channel_modelling_args->timestamp + i + idx) % MAX_CHANNEL_LENGTH]; + : channel_modelling_args->saved_samples[aatx][SAVED_SAMPLES_LEN + idx]; samples[i].r += tx_input.r * impulse_response[l].r - tx_input.i * impulse_response[l].i; samples[i].i += tx_input.i * impulse_response[l].r + tx_input.r * impulse_response[l].i; } @@ -469,6 +466,11 @@ static int vrtsim_write_with_chanmod(vrtsim_state_t *vrtsim_state, int nbAnt, int flags) { + // Sample history for channel impulse response + static c16_t saved_samples[MAX_NUM_ANTENNAS_TX][SAVED_SAMPLES_LEN] __attribute__((aligned(32))) = {0}; + // Indicates what samples are saves in saved_samples + static openair0_timestamp last_timestamp = 0; + AssertFatal(nbAnt < MAX_NUM_ANTENNAS_TX, "Number of antennas %d exceeds maximum %d\n", nbAnt, MAX_NUM_ANTENNAS_TX); for (int aarx = 0; aarx < vrtsim_state->peer_info.num_rx_antennas; aarx++) { notifiedFIFO_elt_t *task = newNotifiedFIFO_elt(sizeof(channel_modelling_args_t), 0, NULL, perform_channel_modelling); @@ -482,25 +484,40 @@ static int vrtsim_write_with_chanmod(vrtsim_state_t *vrtsim_state, for (int i = 0; i < nbAnt; i++) { args->samples[i] = samplesVoid[i]; } + + // Fill in saved_samples + size_t gap_samples = timestamp - last_timestamp; + if (gap_samples > 0) { + size_t gap_samples_needed = min(SAVED_SAMPLES_LEN, gap_samples); + for (int aatx = 0; aatx < nbAnt; aatx++) { + memset(&args->saved_samples[aatx][SAVED_SAMPLES_LEN - gap_samples_needed], 0, sizeof(c16_t) * gap_samples_needed); + if (gap_samples < SAVED_SAMPLES_LEN) { + size_t samples_from_saved = SAVED_SAMPLES_LEN - gap_samples_needed; + memcpy(&args->saved_samples[aatx][0], &saved_samples[aatx][SAVED_SAMPLES_LEN - samples_from_saved], sizeof(c16_t) * samples_from_saved); + } + } + } else { + for (int aatx = 0; aatx < nbAnt; aatx++) + memcpy(&args->saved_samples[aatx][0], saved_samples[aatx], sizeof(c16_t) * SAVED_SAMPLES_LEN); + } + memcpy(args->saved_samples, saved_samples, sizeof(saved_samples)); pushNotifiedFIFO(&vrtsim_state->channel_modelling_actors[aarx].fifo, task); } - int start_index = timestamp % MAX_CHANNEL_LENGTH; - int end_index = min(start_index + nsamps, MAX_CHANNEL_LENGTH); - int cp_nsamps = end_index - start_index; - for (int aatx = 0; aatx < nbAnt; aatx++) { - c16_t *samples = (c16_t *)samplesVoid[aatx]; - memcpy(&saved_samples[aatx][start_index], &samples[0], sizeof(c16_t) * cp_nsamps); - } - if (end_index < start_index + nsamps) { - // wrap around condition, write at beginning of buffer - cp_nsamps = nsamps - cp_nsamps; // remaining samples - start_index = 0; + // Save samples for next round + if (nsamps < SAVED_SAMPLES_LEN) { for (int aatx = 0; aatx < nbAnt; aatx++) { - c16_t *samples = (c16_t *)samplesVoid[aatx]; - memcpy(&saved_samples[aatx][start_index], &samples[0], sizeof(c16_t) * cp_nsamps); + memmove(&saved_samples[aatx][0], &saved_samples[aatx][nsamps], sizeof(c16_t) * (SAVED_SAMPLES_LEN - nsamps)); + memcpy(&saved_samples[aatx][SAVED_SAMPLES_LEN - nsamps], samplesVoid[aatx], sizeof(c16_t) * nsamps); + } + } else { + for (int aatx = 0; aatx < nbAnt; aatx++) { + c16_t* samples = (c16_t*)samplesVoid[aatx]; + memcpy(saved_samples[aatx], &samples[nsamps - SAVED_SAMPLES_LEN], sizeof(c16_t) * (SAVED_SAMPLES_LEN)); } } + + last_timestamp = timestamp + nsamps; return nsamps; } From 8f116f68d2aaa062a8ac9467701f4d7d9465e20f Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Wed, 3 Dec 2025 15:09:19 +0100 Subject: [PATCH 2/8] vrtsim: fix assert for number of TX antennas --- radio/vrtsim/vrtsim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c index 01589797d0..ae47a4d370 100644 --- a/radio/vrtsim/vrtsim.c +++ b/radio/vrtsim/vrtsim.c @@ -471,7 +471,7 @@ static int vrtsim_write_with_chanmod(vrtsim_state_t *vrtsim_state, // Indicates what samples are saves in saved_samples static openair0_timestamp last_timestamp = 0; - AssertFatal(nbAnt < MAX_NUM_ANTENNAS_TX, "Number of antennas %d exceeds maximum %d\n", nbAnt, MAX_NUM_ANTENNAS_TX); + AssertFatal(nbAnt <= MAX_NUM_ANTENNAS_TX, "Number of antennas %d exceeds maximum %d\n", nbAnt, MAX_NUM_ANTENNAS_TX); for (int aarx = 0; aarx < vrtsim_state->peer_info.num_rx_antennas; aarx++) { notifiedFIFO_elt_t *task = newNotifiedFIFO_elt(sizeof(channel_modelling_args_t), 0, NULL, perform_channel_modelling); channel_modelling_args_t *args = (channel_modelling_args_t *)NotifiedFifoData(task); From 9d3670eefd553c5205562d54a26cb8cd45e4ca81 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Wed, 3 Dec 2025 15:25:44 +0100 Subject: [PATCH 3/8] vrtsim: Enable batch processing in perform_channel_modelling In perfrom_channel_modelling, do convolution in batches which allows vrtsim to write the channel samples as they are being produced instead of waiting for the last sample in the slot to be ready. --- radio/vrtsim/vrtsim.c | 88 ++++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c index ae47a4d370..f47c865fcc 100644 --- a/radio/vrtsim/vrtsim.c +++ b/radio/vrtsim/vrtsim.c @@ -372,6 +372,8 @@ typedef struct { int nbAnt; int flags; int aarx; + int batch_size; + int num_batches; c16_t saved_samples[MAX_NUM_ANTENNAS_TX][SAVED_SAMPLES_LEN]; } channel_modelling_args_t; @@ -415,48 +417,55 @@ static void perform_channel_modelling(void *arg) } } - for (int aatx = 0; aatx < nb_tx_ant; aatx++) { - for (int i = 0; i < nsamps; i++) { - cf_t *impulse_response = channel_impulse_response_p[aatx]; - for (int l = 0; l < channel_desc->channel_length; l++) { - int idx = i - l; - // TODO: Use AVX2 for this - c16_t tx_input = idx >= 0 ? input_samples[aatx][idx] - : channel_modelling_args->saved_samples[aatx][SAVED_SAMPLES_LEN + idx]; - samples[i].r += tx_input.r * impulse_response[l].r - tx_input.i * impulse_response[l].i; - samples[i].i += tx_input.i * impulse_response[l].r + tx_input.r * impulse_response[l].i; + for (int batch_index = 0; batch_index < channel_modelling_args->num_batches; batch_index++) { + int start_sample = batch_index * channel_modelling_args->batch_size; + int num_samples = min(channel_modelling_args->batch_size, nsamps - start_sample); + if (start_sample >= nsamps) { + break; + } + for (int aatx = 0; aatx < nb_tx_ant; aatx++) { + for (int i = start_sample; i < start_sample + num_samples; i++) { + cf_t *impulse_response = channel_impulse_response_p[aatx]; + for (int l = 0; l < channel_desc->channel_length; l++) { + int idx = i - l; + // TODO: Use AVX2 for this + c16_t tx_input = idx >= 0 ? input_samples[aatx][idx] + : channel_modelling_args->saved_samples[aatx][SAVED_SAMPLES_LEN + idx]; + samples[i].r += tx_input.r * impulse_response[l].r - tx_input.i * impulse_response[l].i; + samples[i].i += tx_input.i * impulse_response[l].r + tx_input.r * impulse_response[l].i; + } } } - } - // Convert to c16_t - c16_t samples_out[aligned_nsamps] __attribute__((aligned(64))); -#if defined(__AVX512F__) - for (int i = 0; i < aligned_nsamps / 8; i++) { - simde__m512 *in = (simde__m512 *)&samples[i * 8]; - simde__m256i *out = (simde__m256i *)&samples_out[i * 8]; - *out = simde_mm512_cvtsepi32_epi16(simde_mm512_cvtps_epi32(*in)); - } -#elif defined(__AVX2__) - for (int i = 0; i < aligned_nsamps / 4; i++) { - simde__m256 *in = (simde__m256 *)&samples[i * 4]; - simde__m128i *out = (simde__m128i *)&samples_out[i * 4]; - *out = simde_mm256_cvtsepi32_epi16(simde_mm256_cvtps_epi32(*in)); - } -#else - for (int i = 0; i < nsamps; i++) { - samples_out[i].r = lroundf(samples[i].r); - samples_out[i].i = lroundf(samples[i].i); - } -#endif + // Convert to c16_t + c16_t samples_out[aligned_nsamps] __attribute__((aligned(64))); + #if defined(__AVX512F__) + for (int i = 0; i < aligned_nsamps / 8; i++) { + simde__m512 *in = (simde__m512 *)&samples[i * 8]; + simde__m256i *out = (simde__m256i *)&samples_out[i * 8]; + *out = simde_mm512_cvtsepi32_epi16(simde_mm512_cvtps_epi32(*in)); + } + #elif defined(__AVX2__) + for (int i = 0; i < aligned_nsamps / 4; i++) { + simde__m256 *in = (simde__m256 *)&samples[i * 4]; + simde__m128i *out = (simde__m128i *)&samples_out[i * 4]; + *out = simde_mm256_cvtsepi32_epi16(simde_mm256_cvtps_epi32(*in)); + } + #else + for (int i = 0; i < nsamps; i++) { + samples_out[i].r = lroundf(samples[i].r); + samples_out[i].i = lroundf(samples[i].i); + } + #endif - vrtsim_write_internal(channel_modelling_args->vrtsim_state, - channel_modelling_args->timestamp, - samples_out, - channel_modelling_args->nsamps, - aarx, - channel_modelling_args->flags, - aarx); + vrtsim_write_internal(channel_modelling_args->vrtsim_state, + channel_modelling_args->timestamp, + samples_out, + channel_modelling_args->nsamps, + aarx, + channel_modelling_args->flags, + aarx); + } } static int vrtsim_write_with_chanmod(vrtsim_state_t *vrtsim_state, @@ -470,6 +479,7 @@ static int vrtsim_write_with_chanmod(vrtsim_state_t *vrtsim_state, static c16_t saved_samples[MAX_NUM_ANTENNAS_TX][SAVED_SAMPLES_LEN] __attribute__((aligned(32))) = {0}; // Indicates what samples are saves in saved_samples static openair0_timestamp last_timestamp = 0; + const int batch_size = 4096; AssertFatal(nbAnt <= MAX_NUM_ANTENNAS_TX, "Number of antennas %d exceeds maximum %d\n", nbAnt, MAX_NUM_ANTENNAS_TX); for (int aarx = 0; aarx < vrtsim_state->peer_info.num_rx_antennas; aarx++) { @@ -481,6 +491,8 @@ static int vrtsim_write_with_chanmod(vrtsim_state_t *vrtsim_state, args->nbAnt = nbAnt; args->flags = flags; args->aarx = aarx; + args->batch_size = batch_size; + args->num_batches = (nsamps + batch_size - 1) / batch_size; for (int i = 0; i < nbAnt; i++) { args->samples[i] = samplesVoid[i]; } From b9665aac5f0a739f0bd17ca6c52813e158fd8d8f Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Mon, 3 Nov 2025 19:05:39 +0100 Subject: [PATCH 4/8] vrtsim CI testcase with channel modelling Add vrtsim CI testcase with channel modelling. --- .../gnb.sa.band78.106prb.vrtsim.2x2.yaml | 209 ++++++++++++++++++ .../conf_files/nrue.vrtsim.chanmod.yaml | 20 ++ .../xml_files/container_5g_vrtsim_chanmod.xml | 140 ++++++++++++ .../5g_vrtsim_chanmod/docker-compose.yaml | 163 ++++++++++++++ 4 files changed, 532 insertions(+) create mode 100644 ci-scripts/conf_files/gnb.sa.band78.106prb.vrtsim.2x2.yaml create mode 100644 ci-scripts/conf_files/nrue.vrtsim.chanmod.yaml create mode 100644 ci-scripts/xml_files/container_5g_vrtsim_chanmod.xml create mode 100644 ci-scripts/yaml_files/5g_vrtsim_chanmod/docker-compose.yaml diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.vrtsim.2x2.yaml b/ci-scripts/conf_files/gnb.sa.band78.106prb.vrtsim.2x2.yaml new file mode 100644 index 0000000000..5cca2b0718 --- /dev/null +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.vrtsim.2x2.yaml @@ -0,0 +1,209 @@ +Active_gNBs: + - gnb-rfsim +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity: none +gNBs: + ##### Identification parameters: + - gNB_ID: 0xe00 + gNB_name: gnb-rfsim + tracking_area_code: 1 + plmn_list: + - mcc: 208 + mnc: 99 + mnc_length: 2 + snssaiList: + - sst: 1 + sd: 0xffffff + nr_cellid: 12345678 + ##### Physical parameters: + min_rxtxtime: 6 + pusch_AntennaPorts: 2 + pdsch_AntennaPorts_XP: 2 + + servingCellConfigCommon: + #spCellConfigCommon + - physCellId: 0 + # downlinkConfigCommon + #frequencyInfoDL + # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 + absoluteFrequencySSB: 621312 + # this is 3300.60 MHz + dl_absoluteFrequencyPointA: 620040 + #scs-SpecificCarrierList + dl_offstToCarrier: 0 + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing: 1 + dl_carrierBandwidth: 106 + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=106 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth: 28875 + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing: 1 + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero: 11 + initialDLBWPsearchSpaceZero: 0 + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand: 78 + #scs-SpecificCarrierList + ul_offstToCarrier: 0 + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing: 1 + ul_carrierBandwidth: 106 + pMax: 20 + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth: 28875 + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing: 1 + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex: 98 + #prach_msg1_FDM + #0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM: 0 + prach_msg1_FrequencyStart: 0 + zeroCorrelationZoneConfig: 12 + preambleReceivedTargetPower: -104 + #preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax: 6 + #powerRampingStep + # 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep: 1 + #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR + #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR: 4 + #one (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB: 15 + #ra_ContentionResolutionTimer + #(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer: 7 + rsrp_ThresholdSSB: 19 + #prach-RootSequenceIndex_PR + #1 = 839, 2 = 139 + prach_RootSequenceIndex_PR: 2 + prach_RootSequenceIndex: 1 + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + msg1_SubcarrierSpacing: 1 + # restrictedSetConfig + # 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig: 0 + msg3_DeltaPreamble: 1 + p0_NominalWithGrant: -90 + + # pucch-ConfigCommon setup : + # pucchGroupHopping + # 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping: 0 + hoppingId: 40 + p0_nominal: -90 + ssb_PositionsInBurst_Bitmap: 1 + # ssb_periodicityServingCell + # 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell: 2 + + # dmrs_TypeA_position + # 0 = pos2, 1 = pos3 + dmrs_TypeA_Position: 0 + + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing: 1 + + #tdd-UL-DL-ConfigurationCommon + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing: 1 + + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity: 6 + nrofDownlinkSlots: 7 + nrofDownlinkSymbols: 6 + nrofUplinkSlots: 2 + nrofUplinkSymbols: 4 + ssPBCH_BlockPower: -25 + SCTP: + SCTP_INSTREAMS: 2 + SCTP_OUTSTREAMS: 2 + + ##### AMF parameters: + amf_ip_address: + - ipv4: 192.168.71.132 + + NETWORK_INTERFACES: + GNB_IPV4_ADDRESS_FOR_NG_AMF: 192.168.71.140 + GNB_IPV4_ADDRESS_FOR_NGU: 192.168.71.140 + GNB_PORT_FOR_S1U: 2152 # Spec 2152 + + +MACRLCs: + - num_cc: 1 + tr_s_preference: local_L1 + tr_n_preference: local_RRC + pusch_TargetSNRx10: 200 + pucch_TargetSNRx10: 200 + +L1s: + - num_cc: 1 + tr_n_preference: local_mac + prach_dtx_threshold: 200 + # pucch0_dtx_threshold = 150; + +RUs: + - local_rf: yes + nb_tx: 2 + nb_rx: 2 + att_tx: 0 + att_rx: 0 + bands: [78] + max_pdschReferenceSignalPower: -27 + max_rxgain: 75 + eNB_instances: [0] + sf_extension: 0 + +security: + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms: [nea0] + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms: [nia2, nia0] + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering: yes + drb_integrity: no + +log_config: + global_log_level: info + hw_log_level: info + phy_log_level: info + mac_log_level: info + rlc_log_level: info + pdcp_log_level: info + rrc_log_level: info + ngap_log_level: debug + f1ap_log_level: debug + + +channelmod: + max_chan: 10 + modellist: DefaultChannelList + DefaultChannelList: + - model_name: server_tx_channel_model + type: AWGN + ploss_dB: 0 + noise_power_dB: -100 + forgetfact: 0 + offset: 0 + ds_tdl: 0 diff --git a/ci-scripts/conf_files/nrue.vrtsim.chanmod.yaml b/ci-scripts/conf_files/nrue.vrtsim.chanmod.yaml new file mode 100644 index 0000000000..a9488007d7 --- /dev/null +++ b/ci-scripts/conf_files/nrue.vrtsim.chanmod.yaml @@ -0,0 +1,20 @@ +uicc0: + imsi: 208990100001100 + key: fec86ba6eb707ed08905757b1bb44b8f + opc: C42449363BBAD02B66D16BC975D77CC1 + dnn: oai + nssai_sst: 1 + +thread-pool: "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1" + +channelmod: + max_chan: 10; + modellist: DefaultChannelList + DefaultChannelList: + - model_name: client_tx_channel_model + type: AWGN + ploss_dB: 0 + noise_power_dB: -100 + forgetfact: 0 + offset: 0 + ds_tdl: 0 diff --git a/ci-scripts/xml_files/container_5g_vrtsim_chanmod.xml b/ci-scripts/xml_files/container_5g_vrtsim_chanmod.xml new file mode 100644 index 0000000000..6bd16eff1f --- /dev/null +++ b/ci-scripts/xml_files/container_5g_vrtsim_chanmod.xml @@ -0,0 +1,140 @@ + + + vrtsim-5gnr-chanmod + Monolithic gNB vrtsim + chanmod + wrench + + 111111 + 800813 + 000011 + 000012 + 000013 + 020011 + 020012 + 030011 + 030012 + 100011 + 222222 + + + + + Pull_Local_Registry + Pull Images from Local Registry + localhost + oai-gnb oai-nr-ue + + + Create_Workspace + Create new Workspace + localhost + + + Deploy_Object + Deploy OAI 5G CoreNetwork + localhost + ci-scripts/yaml_files/5g_vrtsim_chanmod + mysql oai-amf oai-smf oai-upf oai-ext-dn + + + + Deploy_Object + Deploy OAI 5G gNB+UE RF sim SA + localhost + ci-scripts/yaml_files/5g_vrtsim_chanmod + oai-gnb oai-nr-ue + + + + Attach_UE + Attach OAI UE (Wait for IP) + rfsim5g_ue + localhost + + + + Ping + Ping ext-dn from NR-UE + rfsim5g_ue + localhost + rfsim5g_ext_dn + localhost + -c 20 -i 0.25 + 5 + + + + Ping + Ping NR-UE from ext-dn + rfsim5g_ext_dn + localhost + rfsim5g_ue + localhost + -c 20 -i 0.25 + 5 + + + + Iperf + Iperf (DL/3Mbps/UDP)(20 sec) + -u -b 3M -t 20 -R + rfsim5g_ue + localhost + rfsim5g_ext_dn + localhost + 5 + 90 + + + + Iperf + Iperf (UL/1Mbps/UDP)(20 sec) + -u -b 1M -t 20 + rfsim5g_ue + localhost + rfsim5g_ext_dn + localhost + 5 + 90 + + + + Undeploy_Object + true + Undeploy all OAI 5G stack + localhost + ci-scripts/yaml_files/5g_vrtsim_chanmod + 1,0,0,0 + 1,0,0,0 + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + localhost + oai-gnb oai-nr-ue + + + diff --git a/ci-scripts/yaml_files/5g_vrtsim_chanmod/docker-compose.yaml b/ci-scripts/yaml_files/5g_vrtsim_chanmod/docker-compose.yaml new file mode 100644 index 0000000000..bff7807f22 --- /dev/null +++ b/ci-scripts/yaml_files/5g_vrtsim_chanmod/docker-compose.yaml @@ -0,0 +1,163 @@ +services: + mysql: + container_name: "rfsim5g-mysql" + image: mysql:8.0 + init: true + volumes: + - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql + - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh + environment: + - TZ=Europe/Paris + - MYSQL_DATABASE=oai_db + - MYSQL_USER=test + - MYSQL_PASSWORD=test + - MYSQL_ROOT_PASSWORD=linux + healthcheck: + test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + interval: 10s + timeout: 5s + start_period: 10s + start_interval: 500ms + retries: 30 + networks: + public_net: + ipv4_address: 192.168.71.131 + oai-amf: + container_name: "rfsim5g-oai-amf" + image: oaisoftwarealliance/oai-amf:v2.1.10 + environment: + - TZ=Europe/paris + volumes: + - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-amf/etc/config.yaml + depends_on: + - mysql + networks: + public_net: + ipv4_address: 192.168.71.132 + oai-smf: + container_name: "rfsim5g-oai-smf" + image: oaisoftwarealliance/oai-smf:v2.1.10 + environment: + - TZ=Europe/Paris + volumes: + - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-smf/etc/config.yaml + depends_on: + - oai-amf + networks: + public_net: + ipv4_address: 192.168.71.133 + oai-upf: + container_name: "rfsim5g-oai-upf" + image: oaisoftwarealliance/oai-upf:v2.1.10 + init: true + environment: + - TZ=Europe/Paris + volumes: + - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-upf/etc/config.yaml + depends_on: + - oai-smf + cap_add: + - NET_ADMIN + - SYS_ADMIN + cap_drop: + - ALL + privileged: true + networks: + public_net: + ipv4_address: 192.168.71.134 + interface_name: eth0 + traffic_net: + ipv4_address: 192.168.72.134 + interface_name: eth1 + oai-ext-dn: + privileged: true + container_name: rfsim5g-oai-ext-dn + image: oaisoftwarealliance/trf-gen-cn5g:focal + init: true + entrypoint: /bin/bash -c \ + "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ + "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity" + depends_on: + - oai-upf + networks: + traffic_net: + ipv4_address: 192.168.72.135 + healthcheck: + test: /bin/bash -c "ping -c 2 192.168.72.134" + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s + start_interval: 500ms + oai-gnb: + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: rfsim5g-oai-gnb + cap_drop: + - ALL + environment: + USE_ADDITIONAL_OPTIONS: -E --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role server --vrtsim.chanmod 1 + depends_on: + - oai-ext-dn + networks: + public_net: + ipv4_address: 192.168.71.140 + volumes: + - ../../conf_files/gnb.sa.band78.106prb.vrtsim.2x2.yaml:/opt/oai-gnb/etc/gnb.yaml + - tmp_data:/tmp/ + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + start_period: 10s + start_interval: 500ms + retries: 5 + ipc: host + oai-nr-ue: + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue + cap_drop: + - ALL + cap_add: + - NET_ADMIN # for interface bringup + - NET_RAW # for ping + environment: + USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time --device.name vrtsim + depends_on: + - oai-gnb + networks: + public_net: + ipv4_address: 192.168.71.150 + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - ../../conf_files/nrue.vrtsim.chanmod.yaml:/opt/oai-nr-ue/etc/nr-ue.yaml + - tmp_data:/tmp/ + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s + start_interval: 500ms + ipc: host + +networks: + public_net: + driver: bridge + name: rfsim5g-oai-public-net + ipam: + config: + - subnet: 192.168.71.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-public" + traffic_net: + driver: bridge + name: rfsim5g-oai-traffic-net + ipam: + config: + - subnet: 192.168.72.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-traffic" + +volumes: + tmp_data: From 4ac445ac30fad7f80a2f4c1b046cda31d70c20c0 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Wed, 17 Dec 2025 08:47:52 +0100 Subject: [PATCH 5/8] vrtsim: add randominit() call This is required with the updated gaussZiggurat call. --- radio/vrtsim/vrtsim.c | 1 + 1 file changed, 1 insertion(+) diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c index f47c865fcc..2b40f2f05d 100644 --- a/radio/vrtsim/vrtsim.c +++ b/radio/vrtsim/vrtsim.c @@ -659,6 +659,7 @@ static int vrtsim_set_freq(openair0_device *device, openair0_config_t *openair0_ __attribute__((__visibility__("default"))) int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { + randominit(); vrtsim_state_t *vrtsim_state = calloc_or_fail(1, sizeof(vrtsim_state_t)); vrtsim_readconfig(vrtsim_state); LOG_I(HW, From a44fb9bcf8a0f814e76f38ee44661b050100becd Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Tue, 9 Dec 2025 18:49:10 +0000 Subject: [PATCH 6/8] Change trf-gen-cn5g version for tests on GH trf-gen-cn5g:latest is available on OAI DockerHub for linux/arm64, trf-gen-cn5g:focal is only for linux/amd64 --- ci-scripts/yaml_files/5g_vrtsim_chanmod/docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/yaml_files/5g_vrtsim_chanmod/docker-compose.yaml b/ci-scripts/yaml_files/5g_vrtsim_chanmod/docker-compose.yaml index bff7807f22..503161fc62 100644 --- a/ci-scripts/yaml_files/5g_vrtsim_chanmod/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_vrtsim_chanmod/docker-compose.yaml @@ -72,7 +72,7 @@ services: oai-ext-dn: privileged: true container_name: rfsim5g-oai-ext-dn - image: oaisoftwarealliance/trf-gen-cn5g:focal + image: oaisoftwarealliance/trf-gen-cn5g:latest init: true entrypoint: /bin/bash -c \ "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ From 60f6137d6cff4c1ced8bdb05ad9e8def5c4507be Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Mon, 1 Dec 2025 13:40:53 +0000 Subject: [PATCH 7/8] Add XML file for running vrtsim on ARM --- .../container_5g_vrtsim_chanmod_gh.xml | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 ci-scripts/xml_files/container_5g_vrtsim_chanmod_gh.xml diff --git a/ci-scripts/xml_files/container_5g_vrtsim_chanmod_gh.xml b/ci-scripts/xml_files/container_5g_vrtsim_chanmod_gh.xml new file mode 100644 index 0000000000..3d3fd6ee59 --- /dev/null +++ b/ci-scripts/xml_files/container_5g_vrtsim_chanmod_gh.xml @@ -0,0 +1,141 @@ + + + vrtsim-5gnr-chanmod-gh + Monolithic gNB vrtsim + chanmod + wrench + + 111111 + 800813 + 000011 + 000012 + 000013 + 020011 + 020012 + 030011 + 030012 + 100011 + 222222 + + + + + Pull_Local_Registry + Pull Images from Local Registry + localhost + oai-gnb oai-nr-ue + arm_ + + + Create_Workspace + Create new Workspace + localhost + + + Deploy_Object + Deploy OAI 5G CoreNetwork + localhost + ci-scripts/yaml_files/5g_vrtsim_chanmod + mysql oai-amf oai-smf oai-upf oai-ext-dn + + + + Deploy_Object + Deploy OAI 5G gNB+UE RF sim SA + localhost + ci-scripts/yaml_files/5g_vrtsim_chanmod + oai-gnb oai-nr-ue + + + + Attach_UE + Attach OAI UE (Wait for IP) + rfsim5g_ue + localhost + + + + Ping + Ping ext-dn from NR-UE + rfsim5g_ue + localhost + rfsim5g_ext_dn + localhost + -c 20 -i 0.25 + 5 + + + + Ping + Ping NR-UE from ext-dn + rfsim5g_ext_dn + localhost + rfsim5g_ue + localhost + -c 20 -i 0.25 + 5 + + + + Iperf + Iperf (DL/3Mbps/UDP)(30 sec) + -u -b 3M -t 30 -R + rfsim5g_ue + localhost + rfsim5g_ext_dn + localhost + 5 + 90 + + + + Iperf + Iperf (UL/1Mbps/UDP)(30 sec) + -u -b 1M -t 30 + rfsim5g_ue + localhost + rfsim5g_ext_dn + localhost + 5 + 90 + + + + Undeploy_Object + true + Undeploy all OAI 5G stack + localhost + ci-scripts/yaml_files/5g_vrtsim_chanmod + 1,0,0,0 + 1,0,0,0 + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + localhost + oai-gnb oai-nr-ue + + + From ee4dc21f25279b9db4d7905d1e8a5e23dd442209 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Wed, 17 Dec 2025 13:50:06 +0100 Subject: [PATCH 8/8] CI: Add VRT-Sim test pipeline to parent pipeline --- ci-scripts/Jenkinsfile-GitLab-Container | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index a2bb8112fc..e395973b25 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -380,6 +380,29 @@ pipeline { } } } + stage ("VRT-Sim-Test-5G") { + when { expression {do5Gtest || do5GUeTest} } + steps { + script { + triggerSlaveJob ('RAN-VRT-Sim-Test-5G', 'VRT-Sim-Test-5G') + } + } + post { + always { + script { + // Using a unique variable name for each test stage to avoid overwriting on a global variable + // due to parallel-time concurrency + vrtSim5GStatus = finalizeSlaveJob('RAN-VRT-Sim-Test-5G') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + failingStages += vrtSim5GStatus + } + } + } + } stage ("RF-Sim-Test-5G") { when { expression {do5Gtest || do5GUeTest} } steps {