From aa9183c218047f8c0bb60bc34e467a9acc8356b0 Mon Sep 17 00:00:00 2001 From: Matthias Mehlhose Date: Tue, 13 Aug 2024 10:02:56 +0000 Subject: [PATCH 01/23] mod: Improve signal processing speed of rotate_cpx_vector function --- openair1/PHY/TOOLS/cmult_sv.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/openair1/PHY/TOOLS/cmult_sv.c b/openair1/PHY/TOOLS/cmult_sv.c index c967e1ac9f..b1c9de34ba 100644 --- a/openair1/PHY/TOOLS/cmult_sv.c +++ b/openair1/PHY/TOOLS/cmult_sv.c @@ -160,7 +160,6 @@ void rotate_cpx_vector(const c16_t *const x, const c16_t *const alpha, c16_t *y, int32_t *xd=(int32_t *)x; simde__m128i shift = simde_mm_cvtsi32_si128(output_shift); - register simd_q15_t m0,m1,m2,m3; ((int16_t *)&alpha_128)[0] = alpha->r; ((int16_t *)&alpha_128)[1] = -alpha->i; @@ -174,17 +173,23 @@ void rotate_cpx_vector(const c16_t *const x, const c16_t *const alpha, c16_t *y, for(i=0; i>2; i++) { - m0 = simde_mm_setr_epi32(xd[0],xd[0],xd[1],xd[1]); - m1 = simde_mm_setr_epi32(xd[2],xd[2],xd[3],xd[3]); - m2 = simde_mm_madd_epi16(m0,alpha_128); //complex multiply. result is 32bit [Re Im Re Im] - m3 = simde_mm_madd_epi16(m1,alpha_128); //complex multiply. result is 32bit [Re Im Re Im] - m2 = simde_mm_sra_epi32(m2,shift); // shift right by shift in order to compensate for the input amplitude - m3 = simde_mm_sra_epi32(m3,shift); // shift right by shift in order to compensate for the input amplitude - - y_128[0] = simde_mm_packs_epi32(m2,m3); // pack in 16bit integers with saturation [re im re im re im re im] + y_128[i] = simde_mm_packs_epi32( // pack in 16bit integers with saturation [re im re im re im re im] + simde_mm_sra_epi32( // shift right by shift in order to compensate for the input amplitude + simde_mm_madd_epi16( // complex multiply. result is 32bit [Re Im Re Im] + simde_mm_setr_epi32( xd[0+i*4], xd[0+i*4], xd[1+i*4], xd[1+i*4]), + alpha_128 + ), + shift + ), + simde_mm_sra_epi32( // shift right by shift in order to compensate for the input amplitude + simde_mm_madd_epi16( // complex multiply. result is 32bit [Re Im Re Im] + simde_mm_setr_epi32( xd[2+i*4], xd[2+i*4], xd[3+i*4], xd[3+i*4]), + alpha_128 + ), + shift + ) + ); //print_ints("y_128[0]=", &y_128[0]); - xd+=4; - y_128+=1; } #if defined(__x86__) || defined(__x86_64__) } From 24ff0e294ef73100c8321588a952bd0c59d1b3ee Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 14 Aug 2024 18:56:15 +0200 Subject: [PATCH 02/23] fix to avoid freeing SIB1 information still in use at RRC UE --- openair2/RRC/NR_UE/rrc_UE.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 73be593d14..9de9b2f768 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -700,8 +700,7 @@ static void nr_rrc_ue_prepare_RRCSetupRequest(NR_UE_RRC_INST_t *rrc) nr_rlc_srb_recv_sdu(rrc->ue_id, 0, buf, len); } -void nr_rrc_configure_default_SI(NR_UE_RRC_SI_INFO *SI_info, - NR_SIB1_t *sib1) +static void nr_rrc_configure_default_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SIB1_t *sib1) { struct NR_SI_SchedulingInfo *si_SchedulingInfo = sib1->si_SchedulingInfo; if (!si_SchedulingInfo) @@ -751,11 +750,7 @@ static int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc, switch (bcch_message->message.choice.c1->present) { case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1: LOG_D(NR_RRC, "[UE %ld] Decoding SIB1\n", rrc->ue_id); - asn1cFreeStruc(asn_DEF_NR_SIB1, SI_info->sib1); - NR_SIB1_t *sib1 = bcch_message->message.choice.c1->choice.systemInformationBlockType1; - if(!SI_info->sib1) - SI_info->sib1 = calloc(1, sizeof(*SI_info->sib1)); - memcpy(SI_info->sib1, sib1, sizeof(NR_SIB1_t)); + UPDATE_IE(SI_info->sib1, bcch_message->message.choice.c1->choice.systemInformationBlockType1, NR_SIB1_t); if(g_log->log_component[NR_RRC].level >= OAILOG_DEBUG) xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void *) SI_info->sib1); LOG_A(NR_RRC, "SIB1 decoded\n"); @@ -766,10 +761,10 @@ static int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc, nr_rrc_ue_prepare_RRCSetupRequest(rrc); } // configure default SI - nr_rrc_configure_default_SI(SI_info, sib1); + nr_rrc_configure_default_SI(SI_info, SI_info->sib1); // configure timers and constant - nr_rrc_set_sib1_timers_and_constants(&rrc->timers_and_constants, sib1); - nr_rrc_mac_config_req_sib1(rrc->ue_id, 0, sib1->si_SchedulingInfo, sib1->servingCellConfigCommon); + nr_rrc_set_sib1_timers_and_constants(&rrc->timers_and_constants, SI_info->sib1); + nr_rrc_mac_config_req_sib1(rrc->ue_id, 0, SI_info->sib1->si_SchedulingInfo, SI_info->sib1->servingCellConfigCommon); break; case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation: LOG_I(NR_RRC, "[UE %ld] Decoding SI\n", rrc->ue_id); From 68b07d542c70a8b7053c28b3d5bf0efa3de0ccdf Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 1 Aug 2024 12:42:06 +0200 Subject: [PATCH 03/23] rfsimulator: correctly set center frequency --- openair1/SIMULATION/TOOLS/random_channel.c | 4 ++-- openair1/SIMULATION/TOOLS/sim.h | 2 +- radio/rfsimulator/simulator.c | 8 ++++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/openair1/SIMULATION/TOOLS/random_channel.c b/openair1/SIMULATION/TOOLS/random_channel.c index e9c26e9abd..5c78a3a794 100644 --- a/openair1/SIMULATION/TOOLS/random_channel.c +++ b/openair1/SIMULATION/TOOLS/random_channel.c @@ -2281,7 +2281,7 @@ void init_channelmod(void) { } /* init_channelmod */ -int load_channellist(uint8_t nb_tx, uint8_t nb_rx, double sampling_rate, double channel_bandwidth) { +int load_channellist(uint8_t nb_tx, uint8_t nb_rx, double sampling_rate, uint64_t center_freq, double channel_bandwidth) { paramdef_t achannel_params[] = CHANNELMOD_MODEL_PARAMS_DESC; paramlist_def_t channel_list; memset(&channel_list,0,sizeof(paramlist_def_t)); @@ -2314,7 +2314,7 @@ int load_channellist(uint8_t nb_tx, uint8_t nb_rx, double sampling_rate, double nb_rx, modid, sampling_rate, - 0, + center_freq, channel_bandwidth, *(channel_list.paramarray[i][pindex_DT].dblptr), 0.0, diff --git a/openair1/SIMULATION/TOOLS/sim.h b/openair1/SIMULATION/TOOLS/sim.h index 3b55e7c4e5..9f1e74dd1f 100644 --- a/openair1/SIMULATION/TOOLS/sim.h +++ b/openair1/SIMULATION/TOOLS/sim.h @@ -543,7 +543,7 @@ int modelid_fromstrtype(char *modeltype); double channelmod_get_snr_dB(void); double channelmod_get_sinr_dB(void); void init_channelmod(void) ; -int load_channellist(uint8_t nb_tx, uint8_t nb_rx, double sampling_rate, double channel_bandwidth) ; +int load_channellist(uint8_t nb_tx, uint8_t nb_rx, double sampling_rate, uint64_t center_freq, double channel_bandwidth) ; double N_RB2sampling_rate(uint16_t N_RB); double N_RB2channel_bandwidth(uint16_t N_RB); diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index 0a2ece7d21..82561c9941 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -167,6 +167,7 @@ typedef struct { int rx_num_channels; int tx_num_channels; double sample_rate; + double rx_freq; double tx_bw; int channelmod; double chan_pathloss; @@ -342,7 +343,7 @@ static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { break; } else if (strcmp(rfsimu_params[p].strlistptr[i],"chanmod") == 0) { init_channelmod(); - load_channellist(rfsimulator->tx_num_channels, rfsimulator->rx_num_channels, rfsimulator->sample_rate, rfsimulator->tx_bw); + load_channellist(rfsimulator->tx_num_channels, rfsimulator->rx_num_channels, rfsimulator->sample_rate, rfsimulator->rx_freq, rfsimulator->tx_bw); rfsimulator->channelmod=true; } else { fprintf(stderr, "unknown rfsimulator option: %s\n", rfsimu_params[p].strlistptr[i]); @@ -400,7 +401,7 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, t->rx_num_channels, channelmod, t->sample_rate, - 0, + t->rx_freq, t->tx_bw, 30e-9, // TDL delay-spread parameter 0.0, @@ -963,6 +964,8 @@ static int rfsimulator_stop(openair0_device *device) { return 0; } static int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cfg) { + rfsimulator_state_t* s = device->priv; + s->rx_freq = openair0_cfg->rx_freq[0]; return 0; } static int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) { @@ -980,6 +983,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { rfsimulator->tx_num_channels=openair0_cfg->tx_num_channels; rfsimulator->rx_num_channels=openair0_cfg->rx_num_channels; rfsimulator->sample_rate=openair0_cfg->sample_rate; + rfsimulator->rx_freq=openair0_cfg->rx_freq[0]; rfsimulator->tx_bw=openair0_cfg->tx_bw; rfsimulator_readconfig(rfsimulator); if (rfsimulator->prop_delay_ms > 0.0) From 6a8edaf3176388b469bdf0aa7fcd794d5ba17751 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 1 Aug 2024 12:46:54 +0200 Subject: [PATCH 04/23] rfsimulator: add delay and Doppler simulation for circular orbit and add according channel models SAT_LEO_TRANS and SAT_LEO_REGEN Delay and Doppler computation is done as in Matlab function dopplerShiftCircularOrbit: https://de.mathworks.com/help/satcom/ref/dopplershiftcircularorbit.html --- openair1/SIMULATION/TOOLS/random_channel.c | 39 +++++++- openair1/SIMULATION/TOOLS/sim.h | 16 ++++ radio/rfsimulator/apply_channelmod.c | 102 ++++++++++++++++++--- radio/rfsimulator/simulator.c | 6 ++ 4 files changed, 149 insertions(+), 14 deletions(-) diff --git a/openair1/SIMULATION/TOOLS/random_channel.c b/openair1/SIMULATION/TOOLS/random_channel.c index 5c78a3a794..268d0166b1 100644 --- a/openair1/SIMULATION/TOOLS/random_channel.c +++ b/openair1/SIMULATION/TOOLS/random_channel.c @@ -128,6 +128,7 @@ void fill_channel_desc(channel_desc_t *chan_desc, chan_desc->first_run = 1; chan_desc->ip = 0.0; chan_desc->max_Doppler = max_Doppler; + chan_desc->Doppler_phase_cur = calloc(nb_rx, sizeof(double)); chan_desc->ch = calloc(nb_tx*nb_rx, sizeof(struct complexd *)); chan_desc->chF = calloc(nb_tx*nb_rx, sizeof(struct complexd *)); chan_desc->a = calloc(nb_taps, sizeof(struct complexd *)); @@ -1653,6 +1654,37 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, 0); break; + case SAT_LEO_TRANS: + case SAT_LEO_REGEN: + nb_taps = 1; + Td = 0; + channel_length = 1; + ricean_factor = 0.0; + aoa = 0.0; + maxDoppler = 0; + chan_desc->sat_height = 600e3; + chan_desc->enable_dynamic_delay = true; + chan_desc->enable_dynamic_Doppler = false; // TODO: requires UE to support continuous Doppler estimation, compensation and pre-compensation + fill_channel_desc(chan_desc,nb_tx, + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + NULL, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); + printf("%s: satellite orbit height %f km\n", map_int_to_str(channelmod_names, channel_model), chan_desc->sat_height / 1000); + break; + default: LOG_W(OCM,"channel model not yet supported\n"); free(chan_desc); @@ -1711,6 +1743,7 @@ void free_channel_desc_scm(channel_desc_t *ch) { free(ch->R_sqrt[i]); free(ch->R_sqrt); + free(ch->Doppler_phase_cur); free(ch->ch); free(ch->chF); free(ch->a); @@ -1743,9 +1776,9 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { struct complexd phase, alpha, beta; start_meas(&desc->random_channel); - // For AWGN channel, the received signal (Srx) is equal to transmitted signal (Stx) plus noise (N), i.e., Srx = Stx + N, + // For AWGN and SAT_LEO_* channels, the received signal (Srx) is equal to transmitted signal (Stx) plus noise (N), i.e., Srx = Stx + N, // therefore, the channel matrix is the identity matrix. - if (desc->modelid == AWGN) { + if (desc->modelid == AWGN || desc->modelid == SAT_LEO_TRANS || desc->modelid == SAT_LEO_REGEN) { for (aarx=0; aarxnb_rx; aarx++) { for (aatx = 0; aatx < desc->nb_tx; aatx++) { desc->ch[aarx+(aatx*desc->nb_rx)][0].r = aarx%desc->nb_tx == aatx ? 1.0 : 0.0; @@ -2071,6 +2104,8 @@ static void display_channelmodel(channel_desc_t *cd,int debug, telnet_printfunc_ cd->forgetting_factor); prnt("Initial phase: %lf nb_path: %i \n", cd->ip, cd->nb_paths); + if (cd->modelid == SAT_LEO_TRANS || cd->modelid == SAT_LEO_REGEN) + prnt("satellite orbit height: %f\n", cd->sat_height); for (int i=0; inb_taps ; i++) { prnt("taps: %i lin. ampli. : %lf delay: %lf \n",i,cd->amps[i], cd->delays[i]); diff --git a/openair1/SIMULATION/TOOLS/sim.h b/openair1/SIMULATION/TOOLS/sim.h index 9f1e74dd1f..8297d9c365 100644 --- a/openair1/SIMULATION/TOOLS/sim.h +++ b/openair1/SIMULATION/TOOLS/sim.h @@ -126,6 +126,18 @@ typedef struct { char *model_name; /// flags to properly trigger memory free unsigned int free_flags; + /// time stamp when the time varying channel emulation starts (when client connected) + uint64_t start_TS; + /// height of LEO satellite + float sat_height; + /// flag to enable dynamic delay simulation for LEO satellite + bool enable_dynamic_delay; + /// flag to enable dynamic Doppler simulation for LEO satellite + bool enable_dynamic_Doppler; + /// Doppler phase increment (might vary over time, e.g. for LEO satellite) + float Doppler_phase_inc; + /// current Doppler phase of each RX antenna (for continuous phase from one block to the next) + float *Doppler_phase_cur; } channel_desc_t; typedef struct { @@ -218,6 +230,8 @@ typedef enum { EPA_low, EPA_medium, EPA_high, + SAT_LEO_TRANS, + SAT_LEO_REGEN, } SCM_t; #define CHANNELMOD_MAP_INIT \ {"custom",custom},\ @@ -253,6 +267,8 @@ typedef enum { {"EPA_low",EPA_low},\ {"EPA_medium",EPA_medium},\ {"EPA_high",EPA_high},\ + {"SAT_LEO_TRANS",SAT_LEO_TRANS},\ + {"SAT_LEO_REGEN",SAT_LEO_REGEN},\ {NULL, -1} #define CONFIG_HLP_SNR "Set average SNR in dB (for --siml1 option)\n" diff --git a/radio/rfsimulator/apply_channelmod.c b/radio/rfsimulator/apply_channelmod.c index 917a22924c..5bb207e5be 100644 --- a/radio/rfsimulator/apply_channelmod.c +++ b/radio/rfsimulator/apply_channelmod.c @@ -28,7 +28,7 @@ #include #include #include - +#include #include #include @@ -52,14 +52,85 @@ either we regenerate the channel (call again random_channel(desc,0)), or we keep it over subframes 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, - int rxAnt, - channel_desc_t *channelDesc, - int nbSamples, - uint64_t TS, - uint32_t CirSize - ) { +void rxAddInput(const c16_t *input_sig, + c16_t *after_channel_sig, + int rxAnt, + channel_desc_t *channelDesc, + int nbSamples, + uint64_t TS, + uint32_t CirSize) +{ + if ((channelDesc->sat_height > 0) && (channelDesc->enable_dynamic_delay || channelDesc->enable_dynamic_Doppler)) { // model for transparent satellite on circular orbit + /* assumptions: + - The Earth is spherical, the ground station is static, and that the Earth does not rotate. + - An access or link is possible from the satellite to the ground station at all times. + - The ground station is located at the North Pole (positive Zaxis), and the satellite starts from the initial elevation angle 0° in the second quadrant of the YZplane. + - Satellite moves in the clockwise direction in its circular orbit. + */ + const double radius_earth = 6371e3; // m + const double radius_sat = radius_earth + channelDesc->sat_height; + const double GM_earth = 3.986e14; // m^3/s^2 + const double w_sat = sqrt(GM_earth / (radius_sat * radius_sat * radius_sat)); // rad/s + + // start_time and end_time are when the pos_sat_z == pos_gnb_z (elevation angle == 0 and 180 degree) + const double start_phase = -acos(radius_earth / radius_sat); // SAT is just rising above the horizon + const double end_phase = -start_phase; // SAT is just falling behind the horizon + const double start_time = start_phase / w_sat; // in seconds + const double end_time = end_phase / w_sat; // in seconds + const uint64_t duration_samples = (end_time - start_time) * channelDesc->sampling_rate; + const double t = start_time + ((TS - channelDesc->start_TS) % duration_samples) / channelDesc->sampling_rate; + + const double pos_sat_x = 0; + const double pos_sat_y = radius_sat * sin(w_sat * t); + const double pos_sat_z = radius_sat * cos(w_sat * t); + + const double vel_sat_x = 0; + const double vel_sat_y = w_sat * radius_sat * cos(w_sat * t); + const double vel_sat_z = -w_sat * radius_sat * sin(w_sat * t); + + const double pos_ue_x = 0; + const double pos_ue_y = 0; + const double pos_ue_z = radius_earth; + + const double dir_sat_ue_x = pos_ue_x - pos_sat_x; + const double dir_sat_ue_y = pos_ue_y - pos_sat_y; + const double dir_sat_ue_z = pos_ue_z - pos_sat_z; + + const double dist_sat_ue = sqrt(dir_sat_ue_x * dir_sat_ue_x + dir_sat_ue_y * dir_sat_ue_y + dir_sat_ue_z * dir_sat_ue_z); + const double vel_sat_ue = (vel_sat_x * dir_sat_ue_x + vel_sat_y * dir_sat_ue_y + vel_sat_z * dir_sat_ue_z) / dist_sat_ue; + + double dist_gnb_sat = 0; + double vel_gnb_sat = 0; + if (channelDesc->modelid == SAT_LEO_TRANS) { + const double pos_gnb_x = 0; + const double pos_gnb_y = 0; + const double pos_gnb_z = radius_earth; + + const double dir_gnb_sat_x = pos_sat_x - pos_gnb_x; + const double dir_gnb_sat_y = pos_sat_y - pos_gnb_y; + const double dir_gnb_sat_z = pos_sat_z - pos_gnb_z; + + dist_gnb_sat = sqrt(dir_gnb_sat_x * dir_gnb_sat_x + dir_gnb_sat_y * dir_gnb_sat_y + dir_gnb_sat_z * dir_gnb_sat_z); + vel_gnb_sat = (vel_sat_x * dir_gnb_sat_x + vel_sat_y * dir_gnb_sat_y + vel_sat_z * dir_gnb_sat_z) / dist_gnb_sat; + } + + const double c = 299792458; // m/s + const double prop_delay = (dist_gnb_sat + dist_sat_ue) / c; + if (channelDesc->enable_dynamic_delay) + channelDesc->channel_offset = prop_delay * channelDesc->sampling_rate; + + const double f_Doppler_shift_sat_ue = (vel_sat_ue / (c - vel_sat_ue)) * channelDesc->center_freq; + const double f_Doppler_shift_gnb_sat = (-vel_gnb_sat / c) * channelDesc->center_freq; + if (channelDesc->enable_dynamic_Doppler) + channelDesc->Doppler_phase_inc = 2 * M_PI * (f_Doppler_shift_gnb_sat + f_Doppler_shift_sat_ue) / channelDesc->sampling_rate; + + static uint64_t last_TS = 0; + if(TS - last_TS >= channelDesc->sampling_rate) { + last_TS = TS; + LOG_I(HW, "Satellite orbit: time %f s, Doppler: gNB->SAT %f kHz, SAT->UE %f kHz, Delay %f ms\n", t, f_Doppler_shift_gnb_sat / 1000, f_Doppler_shift_sat_ue / 1000, prop_delay * 1000); + } + } + // channelDesc->path_loss_dB should contain the total path gain // so, in actual RF: tx gain + path loss + rx gain (+antenna gain, ...) // UE and NB gain control to be added @@ -94,9 +165,16 @@ void rxAddInput( const c16_t *input_sig, } //l } - // Fixme: lround(), rount(), ... is detected by valgrind as error, not found why - 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)); + if (channelDesc->Doppler_phase_inc != 0.0) { + double complex in = CMPLX(rx_tmp.r, rx_tmp.i); + double complex out = in * cexp(channelDesc->Doppler_phase_cur[rxAnt] * I); + rx_tmp.r = creal(out); + rx_tmp.i = cimag(out); + channelDesc->Doppler_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++; } diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index 82561c9941..d944e028bb 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -709,6 +709,10 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi samplesVoid[i]=(void *)&v; rfsimulator_write_internal(t, t->lastWroteTS > 1 ? t->lastWroteTS - 1 : 0, samplesVoid, 1, t->tx_num_channels, 1, false); + + buffer_t *b = &t->buf[conn_sock]; + if (b->channel_model) + b->channel_model->start_TS = t->lastWroteTS; } else { if ( events[nbEv].events & (EPOLLHUP | EPOLLERR | EPOLLRDHUP) ) { socketError(t,fd); @@ -761,6 +765,8 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi nsamps_for_initial; LOG_D(HW, "UE got first timestamp: starting at %lu\n", t->nextRxTstamp); b->trashingPacket=true; + if (b->channel_model) + b->channel_model->start_TS = t->nextRxTstamp; } else if (b->lastReceivedTS < b->th.timestamp) { int nbAnt= b->th.nbAnt; From cfb6ed4d82b2cd9419e38bdf0e2c84540779a6d8 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 1 Aug 2024 13:00:58 +0200 Subject: [PATCH 05/23] add example configuration using transparent LEO satellite model for rfsimulator --- .../CONF/channelmod_rfsimu_LEO_satellite.conf | 16 ++++++++++++++++ .../CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf | 5 +++-- .../CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf | 5 +++-- 3 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 targets/PROJECTS/GENERIC-NR-5GC/CONF/channelmod_rfsimu_LEO_satellite.conf diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/channelmod_rfsimu_LEO_satellite.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/channelmod_rfsimu_LEO_satellite.conf new file mode 100644 index 0000000000..47acf0e8b0 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/channelmod_rfsimu_LEO_satellite.conf @@ -0,0 +1,16 @@ +channelmod = { + max_chan=10; + modellist="modellist_rfsimu_1"; + modellist_rfsimu_1 = ( + { + model_name = "rfsimu_channel_enB0" + type = "SAT_LEO_TRANS"; + noise_power_dB = -100; + }, + { + model_name = "rfsimu_channel_ue0" + type = "SAT_LEO_TRANS"; + noise_power_dB = -100; + } + ); +}; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf index de9eb1e547..9adb7ab2c5 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf @@ -165,7 +165,8 @@ gNBs = #ext2 #ntn_Config_r17 -# cellSpecificKoffset_r17 = 478; +# cellSpecificKoffset_r17 = 478; # GEO satellite +# cellSpecificKoffset_r17 = 40; # LEO satellite } ); @@ -255,7 +256,6 @@ rfsimulator : serveraddr = "server"; serverport = 4043; options = (); #("saviq"); or/and "chanmod" - modelname = "AWGN"; IQfile = "/tmp/rfsimulator.iqs"; }; @@ -289,3 +289,4 @@ log_config : f1ap_log_level ="debug"; }; +@include "channelmod_rfsimu_LEO_satellite.conf" diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf index 1f757c45dd..766e51e4d5 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf @@ -165,7 +165,8 @@ gNBs = #ext2 #ntn_Config_r17 -# cellSpecificKoffset_r17 = 478; +# cellSpecificKoffset_r17 = 478; # GEO satellite +# cellSpecificKoffset_r17 = 40; # LEO satellite } ); @@ -255,7 +256,6 @@ rfsimulator : serveraddr = "server"; serverport = 4043; options = (); #("saviq"); or/and "chanmod" - modelname = "AWGN"; IQfile = "/tmp/rfsimulator.iqs"; }; @@ -289,3 +289,4 @@ log_config : f1ap_log_level ="debug"; }; +@include "channelmod_rfsimu_LEO_satellite.conf" From 8ab7f1dd687fbe4bf339ef80f5bac05863a9b007 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 1 Aug 2024 13:08:42 +0200 Subject: [PATCH 06/23] change returned value of UE_dl_preprocessing() in case no sampleShift change from 0 to INT_MAX This now allows to indicate "there was a new sampleShift calculation, and the actual value is 0" additionally to "there was no new sampleShift calculation". --- executables/nr-ue.c | 7 ++----- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 2 +- openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index dca05ea36a..4317f72041 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -597,7 +597,7 @@ void processSlotTX(void *arg) static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, const UE_nr_rxtx_proc_t *proc, int *tx_wait_for_dlsch, nr_phy_data_t *phy_data) { - int sampleShift = 0; + int sampleShift = INT_MAX; NR_DL_FRAME_PARMS *fp = &UE->frame_parms; if (UE->sl_mode == 2) fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params; @@ -991,10 +991,7 @@ void *UE_thread(void *arg) nr_rxtx_thread_data_t *curMsgRx = (nr_rxtx_thread_data_t *)NotifiedFifoData(newRx); *curMsgRx = (nr_rxtx_thread_data_t){.proc = curMsg.proc, .UE = UE}; int ret = UE_dl_preprocessing(UE, &curMsgRx->proc, tx_wait_for_dlsch, &curMsgRx->phy_data); - if (ret) - // if ret is 0, no rx_offset has been computed, - // or the computed value is 0 = no offset to do - // we store it to apply the drift compensation at beginning of next frame + if (ret != INT_MAX) shiftForNextFrame = ret; pushTpool(&(get_nrUE_params()->Tpool), newRx); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 4aff01720b..ce2c6c3153 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -877,7 +877,7 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_ fapi_nr_config_request_t *cfg = &ue->nrUE_config; NR_DL_FRAME_PARMS *fp = &ue->frame_parms; NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config; - int sampleShift = 0; + int sampleShift = INT_MAX; nr_ue_dlsch_init(phy_data->dlsch, NR_MAX_NB_LAYERS>4 ? 2:1, ue->max_ldpc_iterations); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c index 815b1ad4cb..8a409e8ef5 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c @@ -168,7 +168,7 @@ int psbch_pscch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr int nr_slot_rx = proc->nr_slot_rx; sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS; NR_DL_FRAME_PARMS *fp = &sl_phy_params->sl_frame_params; - int sampleShift = 0; + int sampleShift = INT_MAX; // VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX_SL, VCD_FUNCTION_IN); start_meas(&sl_phy_params->phy_proc_sl_rx); From 4039473a70b1466fd71e41df4bb63444e8c2b99f Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 1 Aug 2024 13:16:20 +0200 Subject: [PATCH 07/23] NR_UE: add PI controller to time sync this allows to compensate larger continuous time drift in DL (e.g. large Doppler from LEO satellite) --- executables/nr-ue.c | 2 +- executables/nr-uesoftmodem.h | 6 +++ .../PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c | 42 ++++++++++--------- openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h | 3 -- openair1/PHY/defs_nr_UE.h | 3 +- 5 files changed, 31 insertions(+), 25 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 4317f72041..50e7b68bf5 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -947,7 +947,7 @@ void *UE_thread(void *arg) if (slot_nr == nb_slot_frame - 1) { // we shift of half of measured drift, at each beginning of frame for both rx and tx iq_shift_to_apply = shiftForNextFrame; - shiftForNextFrame = 0; // We will get a new measured offset if we decode PBCH + shiftForNextFrame = -round(UE->max_pos_acc * get_nrUE_params()->time_sync_I); } const int readBlockSize = get_readBlockSize(slot_nr, fp) - iq_shift_to_apply; diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 08cafc8379..984058a939 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -9,6 +9,8 @@ #define CONFIG_HLP_DLSCH_PARA "number of threads for dlsch processing 0 for no parallelization\n" #define CONFIG_HLP_OFFSET_DIV "Divisor for computing OFDM symbol offset in Rx chain (num samples in CP/). Default value is 8. To set the sample offset to 0, set this value ~ 10e6\n" #define CONFIG_HLP_MAX_LDPC_ITERATIONS "Maximum LDPC decoder iterations\n" +#define CONFIG_HLP_TIME_SYNC_P "coefficient for Proportional part of time sync PI controller\n" +#define CONFIG_HLP_TIME_SYNC_I "coefficient for Integrating part of time sync PI controller\n" #define CONFIG_HLP_NTN_KOFFSET "NTN cellSpecificKoffset-r17 (number of slots for a given subcarrier spacing of 15 kHz)\n" #define CONFIG_HLP_NTN_TA_COMMON "NTN ta-Common, but given in ms\n" @@ -59,6 +61,8 @@ {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, .iptr=&(nrUE_params.no_timing_correction), .defintval=0, TYPE_INT, 0}, \ {"SLC", CONFIG_HLP_SLF, 0, .u64ptr=&(sidelink_frequency[0][0]), .defuintval=2600000000,TYPE_UINT64,0}, \ {"num-ues", NULL, 0, .iptr=&(NB_UE_INST), .defuintval=1, TYPE_INT, 0}, \ + {"time-sync-P", CONFIG_HLP_TIME_SYNC_P, 0, .dblptr=&(nrUE_params.time_sync_P), .defdblval=0.5, TYPE_DOUBLE, 0}, \ + {"time-sync-I", CONFIG_HLP_TIME_SYNC_I, 0, .dblptr=&(nrUE_params.time_sync_I), .defdblval=0.2, TYPE_DOUBLE, 0}, \ {"ntn-koffset", CONFIG_HLP_NTN_KOFFSET, 0, .uptr=&(nrUE_params.ntn_koffset), .defuintval=0, TYPE_UINT, 0}, \ {"ntn-ta-common", CONFIG_HLP_NTN_TA_COMMON, 0, .dblptr=&(nrUE_params.ntn_ta_common), .defdblval=0.0, TYPE_DOUBLE, 0}, \ {"agc", CONFIG_HLP_AGC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.agc), .defintval=0, TYPE_INT, 0}, \ @@ -82,6 +86,8 @@ typedef struct { int N_RB_DL; int ssb_start_subcarrier; int ldpc_offload_flag; + double time_sync_P; + double time_sync_I; unsigned int ntn_koffset; double ntn_ta_common; int agc; diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c index 61c12d145a..5b91a068ed 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -24,7 +24,7 @@ #include "PHY/NR_UE_ESTIMATION/nr_estimation.h" #include "PHY/impl_defs_top.h" -#include "executables/softmodem-common.h" +#include "executables/nr-uesoftmodem.h" #include "common/utils/LOG/vcd_signal_dumper.h" //#define DEBUG_PHY @@ -43,12 +43,9 @@ int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, short coef) { int max_val = 0, max_pos = 0; - uint8_t sync_offset = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_IN); - short ncoef = 32767 - coef; - // search for maximum position within the cyclic prefix for (int i = -frame_parms->nb_prefix_samples/2; i < frame_parms->nb_prefix_samples/2; i++) { int temp = 0; @@ -67,32 +64,37 @@ int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, } // filter position to reduce jitter - ue->max_pos_avg = ((ue->max_pos_avg * coef) >> 15) + (max_pos * ncoef); - - int diff = ue->max_pos_avg >> 15; + const int ncoef = 32767 - coef; + ue->max_pos_iir = ((ue->max_pos_iir * coef) >> 15) + (max_pos * ncoef); + const int diff = (ue->max_pos_iir + 16384) >> 15; + // FIXME: Do we really need this hysteresis for FR2? + int sampleShift = diff; if (frame_parms->freq_range == FR2) - sync_offset = 2; - else - sync_offset = 0; + if (abs(diff) <= 2) + sampleShift = 0; - int sampleShift = 0; - if (abs(diff) > (NR_SYNCH_HYST + sync_offset)) - sampleShift = diff; - - const int sample_shift = -(sampleShift / 2); - // reset IIR filter for next offset calculation - ue->max_pos_avg += sample_shift * 32768; + // PI controller + const double PID_P = get_nrUE_params()->time_sync_P; + const double PID_I = get_nrUE_params()->time_sync_I; + int sample_shift = -round(sampleShift * PID_P + ue->max_pos_acc * PID_I); LOG_D(PHY, - "Slot %d: diff = %i, rx_offset (final) = %i : max_pos = %d, max_pos filtered = %ld, max_power = %d\n", + "Frame %d, Slot %d: max_pos = %d, max_pos filtered = %f, diff = %i, sampleShift = %i, max_pos_acc = %d, sample_shift (final) = %d, max_power = %d\n", + frame, slot, + max_pos, + ue->max_pos_iir / 32768.0, diff, sampleShift, - max_pos, - ue->max_pos_avg, + ue->max_pos_acc, + sample_shift, max_val); + // reset IIR filter for next offset calculation + ue->max_pos_iir += -round(sampleShift * PID_P) * 32768; + ue->max_pos_acc += max_pos; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_OUT); return sample_shift; } diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index 0ce6c0d83b..d08cc87f1d 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -29,9 +29,6 @@ * @{ */ -/*!\brief Timing drift hysterisis in samples*/ -#define NR_SYNCH_HYST 1 - /* A function to perform the channel estimation of DL PRS signal */ int nr_prs_channel_estimation(uint8_t gNB_id, uint8_t rsc_id, diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 2ab028b6a9..96eb22049f 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -456,7 +456,8 @@ typedef struct PHY_VARS_NR_UE_s { /// temporary offset during cell search prior to MIB decoding int ssb_offset; uint16_t symbol_offset; /// offset in terms of symbols for detected ssb in sync - int64_t max_pos_avg; /// Timing offset IIR filter + int64_t max_pos_iir; /// Timing offset IIR filter + int max_pos_acc; /// Timing offset accumuluated error for PI filter /// Timing Advance updates variables /// Timing advance update computed from the TA command signalled from gNB From fc4310cda7d410d08ce09aa4c09891cde04784e2 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 1 Aug 2024 13:27:35 +0200 Subject: [PATCH 08/23] fix multi-statement marco asn1cCallocOne() --- common/utils/oai_asn1.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/common/utils/oai_asn1.h b/common/utils/oai_asn1.h index 573fa94d75..600aea1392 100644 --- a/common/utils/oai_asn1.h +++ b/common/utils/oai_asn1.h @@ -216,7 +216,10 @@ static inline uint64_t BIT_STRING_to_uint64(const BIT_STRING_t *asn) { #define asn1cSeqAdd(VaR, PtR) if (ASN_SEQUENCE_ADD(VaR,PtR)!=0) AssertFatal(false, "ASN.1 encoding error " #VaR "\n") #define asn1cCallocOne(VaR, VaLue) \ - VaR = calloc(1,sizeof(*VaR)); *VaR=VaLue + do { \ + VaR = calloc(1,sizeof(*VaR)); \ + *VaR = VaLue; \ + } while (0) #define asn1cCalloc(VaR, lOcPtr) \ typeof(VaR) lOcPtr = VaR = calloc(1,sizeof(*VaR)) #define asn1cSequenceAdd(VaR, TyPe, lOcPtr) \ From e662721310f2a3937e5441ad692668a8ca94df1e Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 1 Aug 2024 13:32:46 +0200 Subject: [PATCH 09/23] NR_UE: make NTN parameter ta_CommonDrift_r17 configurable via command line parameter --ntn-ta-commondrift While we don't have SIB19 support yet, UE gets this parameter from command line, just like --ntn-koffset and --ntn-ta-common. We use this value to initialize the UE's time-tracking PI controller accumulator. This allows to correctly track the time even if the delay is changing significantly (e.g. due to LEO satellite movement). We also use it to compensate for the time drift that happenes while performing the initial sync. --- executables/nr-ue.c | 4 +++- executables/nr-uesoftmodem.h | 3 +++ openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 6 ++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 50e7b68bf5..9eafacee52 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -886,7 +886,9 @@ void *UE_thread(void *arg) stream_status = STREAM_STATUS_SYNCING; syncInFrame(UE, &sync_timestamp, intialSyncOffset); openair0_write_reorder_clear_context(&UE->rfdevice); - shiftForNextFrame = 0; // will be used to track clock drift + UE->max_pos_acc = get_nrUE_params()->ntn_ta_commondrift * 1e-6 * fp->samples_per_frame / get_nrUE_params()->time_sync_I; // ntn_ta_commondrift is in µs/s, max_pos_acc * time_sync_I is in samples/frame + shiftForNextFrame = -(UE->init_sync_frame + trashed_frames + 2) * UE->max_pos_acc * get_nrUE_params()->time_sync_I; // compensate for the time drift that happened during initial sync + LOG_D(PHY, "max_pos_acc = %d, shiftForNextFrame = %d\n", UE->max_pos_acc, shiftForNextFrame); // read in first symbol AssertFatal(fp->ofdm_symbol_size + fp->nb_prefix_samples0 == UE->rfdevice.trx_read_func(&UE->rfdevice, diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 984058a939..5b745cec61 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -13,6 +13,7 @@ #define CONFIG_HLP_TIME_SYNC_I "coefficient for Integrating part of time sync PI controller\n" #define CONFIG_HLP_NTN_KOFFSET "NTN cellSpecificKoffset-r17 (number of slots for a given subcarrier spacing of 15 kHz)\n" #define CONFIG_HLP_NTN_TA_COMMON "NTN ta-Common, but given in ms\n" +#define CONFIG_HLP_NTN_TA_COMMONDRIFT "NTN ta-CommonDrift, but given in µs/s\n" /***************************************************************************************************************************************/ /* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument @@ -65,6 +66,7 @@ {"time-sync-I", CONFIG_HLP_TIME_SYNC_I, 0, .dblptr=&(nrUE_params.time_sync_I), .defdblval=0.2, TYPE_DOUBLE, 0}, \ {"ntn-koffset", CONFIG_HLP_NTN_KOFFSET, 0, .uptr=&(nrUE_params.ntn_koffset), .defuintval=0, TYPE_UINT, 0}, \ {"ntn-ta-common", CONFIG_HLP_NTN_TA_COMMON, 0, .dblptr=&(nrUE_params.ntn_ta_common), .defdblval=0.0, TYPE_DOUBLE, 0}, \ + {"ntn-ta-commondrift", CONFIG_HLP_NTN_TA_COMMONDRIFT, 0, .dblptr=&(nrUE_params.ntn_ta_commondrift), .defdblval=0.0, TYPE_DOUBLE, 0}, \ {"agc", CONFIG_HLP_AGC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.agc), .defintval=0, TYPE_INT, 0}, \ } // clang-format on @@ -90,6 +92,7 @@ typedef struct { double time_sync_I; unsigned int ntn_koffset; double ntn_ta_common; + double ntn_ta_commondrift; int agc; char *usrp_args; char *tx_subdev; diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index fc4212d604..4eddc6b780 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -88,7 +88,7 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) // Fake SIB19 reception for NTN // TODO: remove this and implement the actual SIB19 reception instead! - if (get_nrUE_params()->ntn_koffset || get_nrUE_params()->ntn_ta_common) { + if (get_nrUE_params()->ntn_koffset || get_nrUE_params()->ntn_ta_common || get_nrUE_params()->ntn_ta_commondrift) { NR_SIB19_r17_t *sib19_r17 = calloc(1, sizeof(*sib19_r17)); sib19_r17->ntn_Config_r17 = calloc(1, sizeof(*sib19_r17->ntn_Config_r17)); @@ -98,9 +98,11 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) } // NTN ta-Common-r17 - if (get_nrUE_params()->ntn_ta_common) { + if (get_nrUE_params()->ntn_ta_common || get_nrUE_params()->ntn_ta_commondrift) { sib19_r17->ntn_Config_r17->ta_Info_r17 = calloc(1, sizeof(*sib19_r17->ntn_Config_r17->ta_Info_r17)); sib19_r17->ntn_Config_r17->ta_Info_r17->ta_Common_r17 = get_nrUE_params()->ntn_ta_common / 4.072e-6; // ta-Common-r17 is in units of 4.072e-3 µs, ntn_ta_common is in ms + if (get_nrUE_params()->ntn_ta_commondrift) + asn1cCallocOne(sib19_r17->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17, get_nrUE_params()->ntn_ta_commondrift / 0.2e-3); // is in units of 0.2e-3 µs/s, ntn_ta_commondrift is in µs/s } nr_rrc_mac_config_req_sib19_r17(mac->ue_id, sib19_r17); From 4f12a25ebd9cf695a37cf6968422926f381cde9b Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Tue, 20 Aug 2024 11:51:55 +0200 Subject: [PATCH 10/23] Cleanup NR UE NAS instance handling - Save nas instance id in nr_ue_nas_t and use that for instance determination. - Use correct field in itti message (destinationInstance instead of originInstance) to determine instance - Make sure both destinationInstance and originInstance fields are correct in NAS interface functions. --- openair2/RRC/NR_UE/rrc_UE.c | 6 +- openair3/NAS/NR_UE/nr_nas_msg_sim.c | 97 ++++++++++++++--------------- openair3/NAS/NR_UE/nr_nas_msg_sim.h | 1 + 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 73be593d14..23e2a81e8a 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -188,7 +188,7 @@ static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, if (ie->nonCriticalExtension->dedicatedNAS_MessageList) { struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *tmp = ext->dedicatedNAS_MessageList; for (int i = 0; i < tmp->list.count; i++) { - MessageDef *ittiMsg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NAS_CONN_ESTABLI_CNF); + MessageDef *ittiMsg = itti_alloc_new_message(TASK_RRC_NRUE, rrc->ue_id, NAS_CONN_ESTABLI_CNF); NasConnEstabCnf *msg = &NAS_CONN_ESTABLI_CNF(ittiMsg); msg->errCode = AS_SUCCESS; msg->nasMsg.length = tmp->list.array[i]->size; @@ -1663,7 +1663,7 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, NR_DedicatedNAS_Message_t *dedicatedNAS_Message = dlInformationTransfer->criticalExtensions.choice.dlInformationTransfer->dedicatedNAS_Message; - MessageDef *ittiMsg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NAS_DOWNLINK_DATA_IND); + MessageDef *ittiMsg = itti_alloc_new_message(TASK_RRC_NRUE, rrc->ue_id, NAS_DOWNLINK_DATA_IND); NasDlDataInd *msg = &NAS_DOWNLINK_DATA_IND(ittiMsg); msg->UEid = rrc->ue_id; msg->nasMsg.length = dedicatedNAS_Message->size; @@ -2315,7 +2315,7 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, rrc->rnti = 0; // Indicate the release of the RRC connection to upper layers - MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_NAS_CONN_RELEASE_IND); + MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_NRUE, rrc->ue_id, NR_NAS_CONN_RELEASE_IND); NR_NAS_CONN_RELEASE_IND(msg_p).cause = release_cause; itti_send_msg_to_task(TASK_NAS_NRUE, rrc->ue_id, msg_p); } diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.c b/openair3/NAS/NR_UE/nr_nas_msg_sim.c index ed0078b610..bc0ca8e0ac 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg_sim.c +++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.c @@ -52,8 +52,10 @@ #include "openair3/SECU/nas_stream_eia2.h" #include "openair3/UTILS/conversions.h" +#define MAX_NAS_UE 4 + extern uint16_t NB_UE_INST; -static nr_ue_nas_t nr_ue_nas = {0}; +static nr_ue_nas_t nr_ue_nas[MAX_NAS_UE] = {0}; static nr_nas_msg_snssai_t nas_allowed_nssai[8]; typedef enum { @@ -478,10 +480,12 @@ void derive_ue_keys(uint8_t *buf, nr_ue_nas_t *nas) { nr_ue_nas_t *get_ue_nas_info(module_id_t module_id) { - DevAssert(module_id == 0); - if (!nr_ue_nas.uicc) - nr_ue_nas.uicc = checkUicc(0); - return &nr_ue_nas; + DevAssert(module_id < MAX_NAS_UE); + if (!nr_ue_nas[module_id].uicc) { + nr_ue_nas[module_id].uicc = checkUicc(module_id); + nr_ue_nas[module_id].UE_id = module_id; + } + return &nr_ue_nas[module_id]; } void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) @@ -613,7 +617,7 @@ static void generateAuthenticationResp(nr_ue_nas_t *nas, as_nas_info_t *initialN int nas_itti_kgnb_refresh_req(instance_t instance, const uint8_t kgnb[32]) { MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_KENB_REFRESH_REQ); + message_p = itti_alloc_new_message(TASK_NAS_NRUE, instance, NAS_KENB_REFRESH_REQ); memcpy(NAS_KENB_REFRESH_REQ(message_p).kenb, kgnb, sizeof(NAS_KENB_REFRESH_REQ(message_p).kenb)); return itti_send_msg_to_task(TASK_RRC_NRUE, instance, message_p); } @@ -691,7 +695,7 @@ static void generateSecurityModeComplete(nr_ue_nas_t *nas, as_nas_info_t *initia } } -static void handle_security_mode_command(instance_t instance, nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, uint8_t *pdu, int pdu_length) +static void handle_security_mode_command(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, uint8_t *pdu, int pdu_length) { /* retrieve integrity and ciphering algorithms */ AssertFatal(pdu_length > 10, "nas: bad pdu\n"); @@ -721,7 +725,7 @@ static void handle_security_mode_command(instance_t instance, nr_ue_nas_t *nas, /* todo: stream_security_container_delete() is not called anywhere, deal with that */ nas->security_container = stream_security_container_init(ciphering_algorithm, integrity_algorithm, knas_enc, knas_int); - nas_itti_kgnb_refresh_req(instance, nas->security.kgnb); + nas_itti_kgnb_refresh_req(nas->UE_id, nas->security.kgnb); generateSecurityModeComplete(nas, initialNasMsg); } @@ -1057,22 +1061,22 @@ error: return 0; } -static void send_nas_uplink_data_req(instance_t instance, const as_nas_info_t *initial_nas_msg) +static void send_nas_uplink_data_req(nr_ue_nas_t *nas, const as_nas_info_t *initial_nas_msg) { - MessageDef *msg = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_UPLINK_DATA_REQ); + MessageDef *msg = itti_alloc_new_message(TASK_NAS_NRUE, nas->UE_id, NAS_UPLINK_DATA_REQ); ul_info_transfer_req_t *req = &NAS_UPLINK_DATA_REQ(msg); - req->UEid = instance; + req->UEid = nas->UE_id; req->nasMsg.data = (uint8_t *) initial_nas_msg->data; req->nasMsg.length = initial_nas_msg->length; - itti_send_msg_to_task(TASK_RRC_NRUE, instance, msg); + itti_send_msg_to_task(TASK_RRC_NRUE, nas->UE_id, msg); } -static void send_nas_detach_req(instance_t instance, bool wait_release) +static void send_nas_detach_req(nr_ue_nas_t *nas, bool wait_release) { - MessageDef *msg = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_DETACH_REQ); + MessageDef *msg = itti_alloc_new_message(TASK_NAS_NRUE, nas->UE_id, NAS_DETACH_REQ); nas_detach_req_t *req = &NAS_DETACH_REQ(msg); req->wait_release = wait_release; - itti_send_msg_to_task(TASK_RRC_NRUE, instance, msg); + itti_send_msg_to_task(TASK_RRC_NRUE, nas->UE_id, msg); } static void parse_allowed_nssai(nr_nas_msg_snssai_t nssaiList[8], const uint8_t *buf, const uint32_t len) @@ -1171,14 +1175,14 @@ static void get_allowed_nssai(nr_nas_msg_snssai_t nssai[8], const uint8_t *pdu_b } } -static void request_default_pdusession(int instance, int nssai_idx) +static void request_default_pdusession(nr_ue_nas_t *nas, int nssai_idx) { - MessageDef *message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_PDU_SESSION_REQ); + MessageDef *message_p = itti_alloc_new_message(TASK_NAS_NRUE, nas->UE_id, NAS_PDU_SESSION_REQ); NAS_PDU_SESSION_REQ(message_p).pdusession_id = 10; /* first or default pdu session */ NAS_PDU_SESSION_REQ(message_p).pdusession_type = 0x91; // 0x91 = IPv4, 0x92 = IPv6, 0x93 = IPv4v6 NAS_PDU_SESSION_REQ(message_p).sst = nas_allowed_nssai[nssai_idx].sst; NAS_PDU_SESSION_REQ(message_p).sd = nas_allowed_nssai[nssai_idx].sd; - itti_send_msg_to_task(TASK_NAS_NRUE, instance, message_p); + itti_send_msg_to_task(TASK_NAS_NRUE, nas->UE_id, message_p); } static int get_user_nssai_idx(const nr_nas_msg_snssai_t allowed_nssai[8], const nr_ue_nas_t *nas) @@ -1193,14 +1197,17 @@ static int get_user_nssai_idx(const nr_nas_msg_snssai_t allowed_nssai[8], const void *nas_nrue_task(void *args_p) { - nr_ue_nas.uicc = checkUicc(0); + for (int UE_id = 0; UE_id < NB_UE_INST; UE_id++) { + // This sets UE uicc from command line. Needs to be called 2 seconds into nr-ue runtime, otherwise the unused command line + // arguments will be reported as unused and the modem asserts. + (void)get_ue_nas_info(UE_id); + } while (1) { nas_nrue(NULL); } } -static void handle_registration_accept(instance_t instance, - nr_ue_nas_t *nas, +static void handle_registration_accept(nr_ue_nas_t *nas, const uint8_t *pdu_buffer, uint32_t msg_length) { @@ -1211,27 +1218,25 @@ static void handle_registration_accept(instance_t instance, as_nas_info_t initialNasMsg = {0}; generateRegistrationComplete(nas, &initialNasMsg, NULL); if (initialNasMsg.length > 0) { - send_nas_uplink_data_req(instance, &initialNasMsg); + send_nas_uplink_data_req(nas, &initialNasMsg); LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message(RegistrationComplete)\n"); } const int nssai_idx = get_user_nssai_idx(nas_allowed_nssai, nas); if (nssai_idx < 0) { LOG_E(NAS, "NSSAI parameters not match with allowed NSSAI. Couldn't request PDU session.\n"); } else { - request_default_pdusession(instance, nssai_idx); + request_default_pdusession(nas, nssai_idx); } } void *nas_nrue(void *args_p) { // Wait for a message or an event - nr_ue_nas.uicc = checkUicc(0); MessageDef *msg_p; itti_receive_msg(TASK_NAS_NRUE, &msg_p); if (msg_p != NULL) { - instance_t instance = msg_p->ittiMsgHeader.originInstance; - AssertFatal(instance == 0, "cannot handle more than one UE!\n"); + nr_ue_nas_t *nas = get_ue_nas_info(msg_p->ittiMsgHeader.destinationInstance); switch (ITTI_MSG_ID(msg_p)) { case INITIALIZE_MESSAGE: @@ -1248,7 +1253,7 @@ void *nas_nrue(void *args_p) case NAS_CELL_SELECTION_CNF: LOG_I(NAS, "[UE %ld] Received %s: errCode %u, cellID %u, tac %u\n", - instance, + nas->UE_id, ITTI_MSG_NAME(msg_p), NAS_CELL_SELECTION_CNF(msg_p).errCode, NAS_CELL_SELECTION_CNF(msg_p).cellID, @@ -1263,7 +1268,7 @@ void *nas_nrue(void *args_p) case NAS_CELL_SELECTION_IND: LOG_I(NAS, "[UE %ld] Received %s: cellID %u, tac %u\n", - instance, + nas->UE_id, ITTI_MSG_NAME(msg_p), NAS_CELL_SELECTION_IND(msg_p).cellID, NAS_CELL_SELECTION_IND(msg_p).tac); @@ -1272,7 +1277,7 @@ void *nas_nrue(void *args_p) break; case NAS_PAGING_IND: - LOG_I(NAS, "[UE %ld] Received %s: cause %u\n", instance, ITTI_MSG_NAME(msg_p), NAS_PAGING_IND(msg_p).cause); + LOG_I(NAS, "[UE %ld] Received %s: cause %u\n", nas->UE_id, ITTI_MSG_NAME(msg_p), NAS_PAGING_IND(msg_p).cause); /* TODO not processed by NAS currently */ break; @@ -1280,10 +1285,9 @@ void *nas_nrue(void *args_p) case NAS_PDU_SESSION_REQ: { as_nas_info_t pduEstablishMsg = {0}; nas_pdu_session_req_t *pduReq = &NAS_PDU_SESSION_REQ(msg_p); - nr_ue_nas_t *nas = get_ue_nas_info(0); generatePduSessionEstablishRequest(nas, &pduEstablishMsg, pduReq); if (pduEstablishMsg.length > 0) { - send_nas_uplink_data_req(instance, &pduEstablishMsg); + send_nas_uplink_data_req(nas, &pduEstablishMsg); LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message(PduSessionEstablishRequest)\n"); } break; @@ -1292,7 +1296,7 @@ void *nas_nrue(void *args_p) case NAS_CONN_ESTABLI_CNF: { LOG_I(NAS, "[UE %ld] Received %s: errCode %u, length %u\n", - instance, + nas->UE_id, ITTI_MSG_NAME(msg_p), NAS_CONN_ESTABLI_CNF(msg_p).errCode, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length); @@ -1300,8 +1304,6 @@ void *nas_nrue(void *args_p) uint8_t *pdu_buffer = NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.data; int pdu_length = NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length; - nr_ue_nas_t *nas = get_ue_nas_info(0); - security_state_t security_state = nas_security_rx_process(nas, pdu_buffer, pdu_length); if (security_state != NAS_SECURITY_INTEGRITY_PASSED && security_state != NAS_SECURITY_NO_SECURITY_CONTEXT) { @@ -1312,7 +1314,7 @@ void *nas_nrue(void *args_p) int msg_type = get_msg_type(pdu_buffer, pdu_length); if (msg_type == REGISTRATION_ACCEPT) { - handle_registration_accept(instance, nas, pdu_buffer, pdu_length); + handle_registration_accept(nas, pdu_buffer, pdu_length); } else if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) { capture_pdu_session_establishment_accept_msg(pdu_buffer, pdu_length); } @@ -1322,8 +1324,7 @@ void *nas_nrue(void *args_p) case NR_NAS_CONN_RELEASE_IND: LOG_I(NAS, "[UE %ld] Received %s: cause %u\n", - instance, ITTI_MSG_NAME (msg_p), NR_NAS_CONN_RELEASE_IND (msg_p).cause); - nr_ue_nas_t *nas = get_ue_nas_info(0); + nas->UE_id, ITTI_MSG_NAME (msg_p), NR_NAS_CONN_RELEASE_IND (msg_p).cause); // TODO handle connection release if (nas->termination_procedure) { /* the following is not clean, but probably necessary: we need to give @@ -1338,7 +1339,7 @@ void *nas_nrue(void *args_p) case NAS_UPLINK_DATA_CNF: LOG_I(NAS, "[UE %ld] Received %s: UEid %u, errCode %u\n", - instance, + nas->UE_id, ITTI_MSG_NAME(msg_p), NAS_UPLINK_DATA_CNF(msg_p).UEid, NAS_UPLINK_DATA_CNF(msg_p).errCode); @@ -1346,33 +1347,31 @@ void *nas_nrue(void *args_p) break; case NAS_DEREGISTRATION_REQ: { - LOG_I(NAS, "[UE %ld] Received %s\n", instance, ITTI_MSG_NAME(msg_p)); - nr_ue_nas_t *nas = get_ue_nas_info(0); + LOG_I(NAS, "[UE %ld] Received %s\n", nas->UE_id, ITTI_MSG_NAME(msg_p)); nas_deregistration_req_t *req = &NAS_DEREGISTRATION_REQ(msg_p); if (nas->guti) { if (req->cause == AS_DETACH) { nas->termination_procedure = true; - send_nas_detach_req(instance, true); + send_nas_detach_req(nas, true); } as_nas_info_t initialNasMsg = {0}; generateDeregistrationRequest(nas, &initialNasMsg, req); - send_nas_uplink_data_req(instance, &initialNasMsg); + send_nas_uplink_data_req(nas, &initialNasMsg); } else { LOG_W(NAS, "No GUTI, cannot trigger deregistration request.\n"); if (req->cause == AS_DETACH) - send_nas_detach_req(instance, false); + send_nas_detach_req(nas, false); } } break; case NAS_DOWNLINK_DATA_IND: { LOG_I(NAS, "[UE %ld] Received %s: length %u , buffer %p\n", - instance, + nas->UE_id, ITTI_MSG_NAME(msg_p), NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length, NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.data); as_nas_info_t initialNasMsg = {0}; - nr_ue_nas_t *nas = get_ue_nas_info(0); uint8_t *pdu_buffer = NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.data; int pdu_length = NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length; @@ -1402,13 +1401,13 @@ void *nas_nrue(void *args_p) generateAuthenticationResp(nas, &initialNasMsg, pdu_buffer); break; case FGS_SECURITY_MODE_COMMAND: - handle_security_mode_command(instance, nas, &initialNasMsg, pdu_buffer, pdu_length); + handle_security_mode_command(nas, &initialNasMsg, pdu_buffer, pdu_length); break; case FGS_DOWNLINK_NAS_TRANSPORT: decodeDownlinkNASTransport(&initialNasMsg, pdu_buffer); break; case REGISTRATION_ACCEPT: - handle_registration_accept(instance, nas, pdu_buffer, pdu_length); + handle_registration_accept(nas, pdu_buffer, pdu_length); break; case FGS_DEREGISTRATION_ACCEPT: LOG_I(NAS, "received deregistration accept\n"); @@ -1448,11 +1447,11 @@ void *nas_nrue(void *args_p) } if (initialNasMsg.length > 0) - send_nas_uplink_data_req(instance, &initialNasMsg); + send_nas_uplink_data_req(nas, &initialNasMsg); } break; default: - LOG_E(NAS, "[UE %ld] Received unexpected message %s\n", instance, ITTI_MSG_NAME(msg_p)); + LOG_E(NAS, "[UE %ld] Received unexpected message %s\n", nas->UE_id, ITTI_MSG_NAME(msg_p)); break; } diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.h b/openair3/NAS/NR_UE/nr_nas_msg_sim.h index 637004f95e..c52096107d 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg_sim.h +++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.h @@ -105,6 +105,7 @@ typedef struct { bool termination_procedure; uint8_t *registration_request_buf; uint32_t registration_request_len; + instance_t UE_id; } nr_ue_nas_t; typedef enum fgs_protocol_discriminator_e { From 50f8f3de58ae4a104ec304c0515da9c08bc9e1d5 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Fri, 23 Aug 2024 10:45:45 +0200 Subject: [PATCH 11/23] Fix formatting in nr_nas_msg_sim.c --- openair3/NAS/NR_UE/nr_nas_msg_sim.c | 418 ++++++++++++++-------------- 1 file changed, 210 insertions(+), 208 deletions(-) diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.c b/openair3/NAS/NR_UE/nr_nas_msg_sim.c index bc0ca8e0ac..0baab7b65c 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg_sim.c +++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.c @@ -29,7 +29,6 @@ * 2023.01.27 Vladimir Dorovskikh 16 digits IMEISV */ - #include // memset #include // malloc, free @@ -100,13 +99,13 @@ security_state_t nas_security_rx_process(nr_ue_nas_t *nas, uint8_t *pdu_buffer, /* check integrity */ uint8_t computed_mac[4]; nas_stream_cipher_t stream_cipher; - stream_cipher.context = nas->security_container->integrity_context; - stream_cipher.count = nas->security.nas_count_dl; - stream_cipher.bearer = 1; /* todo: don't hardcode */ - stream_cipher.direction = 1; - stream_cipher.message = pdu_buffer + 6; + stream_cipher.context = nas->security_container->integrity_context; + stream_cipher.count = nas->security.nas_count_dl; + stream_cipher.bearer = 1; /* todo: don't hardcode */ + stream_cipher.direction = 1; + stream_cipher.message = pdu_buffer + 6; /* length in bits */ - stream_cipher.blength = (pdu_length - 6) << 3; + stream_cipher.blength = (pdu_length - 6) << 3; stream_compute_integrity(nas->security_container->integrity_algorithm, &stream_cipher, computed_mac); uint8_t *received_mac = pdu_buffer + 2; @@ -116,13 +115,13 @@ security_state_t nas_security_rx_process(nr_ue_nas_t *nas, uint8_t *pdu_buffer, /* decipher */ uint8_t buf[pdu_length - 7]; - stream_cipher.context = nas->security_container->ciphering_context; - stream_cipher.count = nas->security.nas_count_dl; - stream_cipher.bearer = 1; /* todo: don't hardcode */ - stream_cipher.direction = 1; - stream_cipher.message = pdu_buffer + 7; + stream_cipher.context = nas->security_container->ciphering_context; + stream_cipher.count = nas->security.nas_count_dl; + stream_cipher.bearer = 1; /* todo: don't hardcode */ + stream_cipher.direction = 1; + stream_cipher.message = pdu_buffer + 7; /* length in bits */ - stream_cipher.blength = (pdu_length - 7) << 3; + stream_cipher.blength = (pdu_length - 7) << 3; stream_compute_encrypt(nas->security_container->ciphering_algorithm, &stream_cipher, buf); memcpy(pdu_buffer + 7, buf, pdu_length - 7); @@ -131,10 +130,7 @@ security_state_t nas_security_rx_process(nr_ue_nas_t *nas, uint8_t *pdu_buffer, return NAS_SECURITY_INTEGRITY_PASSED; } -static int nas_protected_security_header_encode( - char *buffer, - const fgs_nas_message_security_header_t *header, - int length) +static int nas_protected_security_header_encode(char *buffer, const fgs_nas_message_security_header_t *header, int length) { LOG_FUNC_IN; @@ -144,18 +140,18 @@ static int nas_protected_security_header_encode( ENCODE_U8(buffer, header->protocol_discriminator, size); /* Encode the security header type */ - ENCODE_U8(buffer+size, (header->security_header_type & 0xf), size); + ENCODE_U8(buffer + size, (header->security_header_type & 0xf), size); /* Encode the message authentication code */ - ENCODE_U32(buffer+size, header->message_authentication_code, size); + ENCODE_U32(buffer + size, header->message_authentication_code, size); /* Encode the sequence number */ - ENCODE_U8(buffer+size, header->sequence_number, size); + ENCODE_U8(buffer + size, header->sequence_number, size); - LOG_FUNC_RETURN (size); + LOG_FUNC_RETURN(size); } -static int _nas_mm_msg_encode_header(const mm_msg_header_t *header, - uint8_t *buffer, uint32_t len) { +static int _nas_mm_msg_encode_header(const mm_msg_header_t *header, uint8_t *buffer, uint32_t len) +{ int size = 0; /* Check the buffer length */ @@ -165,8 +161,7 @@ static int _nas_mm_msg_encode_header(const mm_msg_header_t *header, /* Check the protocol discriminator */ if (header->ex_protocol_discriminator != FGS_MOBILITY_MANAGEMENT_MESSAGE) { - LOG_TRACE(ERROR, "ESM-MSG - Unexpected extened protocol discriminator: 0x%x", - header->ex_protocol_discriminator); + LOG_TRACE(ERROR, "ESM-MSG - Unexpected extened protocol discriminator: 0x%x", header->ex_protocol_discriminator); return (TLV_ENCODE_PROTOCOL_NOT_SUPPORTED); } @@ -201,7 +196,7 @@ static int fill_guti(FGSMobileIdentity *mi, const Guti5GSMobileIdentity_t *guti) static int fill_imeisv(FGSMobileIdentity *mi, const uicc_t *uicc) { - int i=0; + int i = 0; mi->imeisv.typeofidentity = FGS_MOBILE_IDENTITY_IMEISV; mi->imeisv.digittac01 = getImeisvDigit(uicc, i++); mi->imeisv.digittac02 = getImeisvDigit(uicc, i++); @@ -219,31 +214,33 @@ static int fill_imeisv(FGSMobileIdentity *mi, const uicc_t *uicc) mi->imeisv.digit14 = getImeisvDigit(uicc, i++); mi->imeisv.digitsv1 = getImeisvDigit(uicc, i++); mi->imeisv.digitsv2 = getImeisvDigit(uicc, i++); - mi->imeisv.spare = 0x0f; + mi->imeisv.spare = 0x0f; mi->imeisv.oddeven = 0; return 19; } -int mm_msg_encode(MM_msg *mm_msg, uint8_t *buffer, uint32_t len) { +int mm_msg_encode(MM_msg *mm_msg, uint8_t *buffer, uint32_t len) +{ LOG_FUNC_IN; int header_result; int encode_result; uint8_t msg_type = mm_msg->header.message_type; - /* First encode the EMM message header */ header_result = _nas_mm_msg_encode_header(&mm_msg->header, buffer, len); if (header_result < 0) { - LOG_TRACE(ERROR, "EMM-MSG - Failed to encode EMM message header " - "(%d)", header_result); + LOG_TRACE(ERROR, + "EMM-MSG - Failed to encode EMM message header " + "(%d)", + header_result); LOG_FUNC_RETURN(header_result); } buffer += header_result; len -= header_result; - switch(msg_type) { + switch (msg_type) { case REGISTRATION_REQUEST: encode_result = encode_registration_request(&mm_msg->registration_request, buffer, len); break; @@ -260,32 +257,36 @@ int mm_msg_encode(MM_msg *mm_msg, uint8_t *buffer, uint32_t len) { encode_result = encode_fgs_uplink_nas_transport(&mm_msg->uplink_nas_transport, buffer, len); break; case FGS_DEREGISTRATION_REQUEST_UE_ORIGINATING: - encode_result = encode_fgs_deregistration_request_ue_originating(&mm_msg->fgs_deregistration_request_ue_originating, buffer, len); + encode_result = + encode_fgs_deregistration_request_ue_originating(&mm_msg->fgs_deregistration_request_ue_originating, buffer, len); break; default: - LOG_TRACE(ERROR, "EMM-MSG - Unexpected message type: 0x%x", - mm_msg->header.message_type); + LOG_TRACE(ERROR, "EMM-MSG - Unexpected message type: 0x%x", mm_msg->header.message_type); encode_result = TLV_ENCODE_WRONG_MESSAGE_TYPE; break; /* TODO: Handle not standard layer 3 messages: SERVICE_REQUEST */ } if (encode_result < 0) { - LOG_TRACE(ERROR, "EMM-MSG - Failed to encode L3 EMM message 0x%x " - "(%d)", mm_msg->header.message_type, encode_result); + LOG_TRACE(ERROR, + "EMM-MSG - Failed to encode L3 EMM message 0x%x " + "(%d)", + mm_msg->header.message_type, + encode_result); } if (encode_result < 0) - LOG_FUNC_RETURN (encode_result); + LOG_FUNC_RETURN(encode_result); - LOG_FUNC_RETURN (header_result + encode_result); + LOG_FUNC_RETURN(header_result + encode_result); } -void transferRES(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16], uint8_t *output, uicc_t* uicc) { - uint8_t S[100]={0}; +void transferRES(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16], uint8_t *output, uicc_t *uicc) +{ + uint8_t S[100] = {0}; S[0] = 0x6B; - servingNetworkName (S+1, uicc->imsiStr, uicc->nmc_size); - int netNamesize = strlen((char*)S+1); + servingNetworkName(S + 1, uicc->imsiStr, uicc->nmc_size); + int netNamesize = strlen((char *)S + 1); S[1 + netNamesize] = (netNamesize & 0xff00) >> 8; S[2 + netNamesize] = (netNamesize & 0x00ff); for (int i = 0; i < 16; i++) @@ -297,7 +298,7 @@ void transferRES(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16 S[29 + netNamesize] = 0x00; S[30 + netNamesize] = 0x08; - uint8_t plmn[3] = { 0x02, 0xf8, 0x39 }; + uint8_t plmn[3] = {0x02, 0xf8, 0x39}; uint8_t oldS[100]; oldS[0] = 0x6B; memcpy(&oldS[1], plmn, 3); @@ -312,10 +313,9 @@ void transferRES(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16 oldS[32] = 0x00; oldS[33] = 0x08; - uint8_t key[32] = {0}; memcpy(&key[0], ck, 16); - memcpy(&key[16], ik, 16); //KEY + memcpy(&key[16], ik, 16); // KEY uint8_t out[32] = {0}; byte_array_t data = {.buf = S, .len = 31 + netNamesize}; @@ -324,44 +324,47 @@ void transferRES(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16 memcpy(output, out + 16, 16); } -void derive_kausf(uint8_t ck[16], uint8_t ik[16], uint8_t sqn[6], uint8_t kausf[32], uicc_t *uicc) { - uint8_t S[100]={0}; +void derive_kausf(uint8_t ck[16], uint8_t ik[16], uint8_t sqn[6], uint8_t kausf[32], uicc_t *uicc) +{ + uint8_t S[100] = {0}; uint8_t key[32] = {0}; memcpy(&key[0], ck, 16); - memcpy(&key[16], ik, 16); //KEY + memcpy(&key[16], ik, 16); // KEY S[0] = 0x6A; - servingNetworkName (S+1, uicc->imsiStr, uicc->nmc_size); - int netNamesize = strlen((char*)S+1); + servingNetworkName(S + 1, uicc->imsiStr, uicc->nmc_size); + int netNamesize = strlen((char *)S + 1); S[1 + netNamesize] = (uint8_t)((netNamesize & 0xff00) >> 8); S[2 + netNamesize] = (uint8_t)(netNamesize & 0x00ff); for (int i = 0; i < 6; i++) { - S[3 + netNamesize + i] = sqn[i]; + S[3 + netNamesize + i] = sqn[i]; } S[9 + netNamesize] = 0x00; S[10 + netNamesize] = 0x06; - byte_array_t data = {.buf = S, .len = 11 + netNamesize}; + byte_array_t data = {.buf = S, .len = 11 + netNamesize}; kdf(key, data, 32, kausf); } -void derive_kseaf(uint8_t kausf[32], uint8_t kseaf[32], uicc_t *uicc) { - uint8_t S[100]={0}; - S[0] = 0x6C; //FC - servingNetworkName (S+1, uicc->imsiStr, uicc->nmc_size); - int netNamesize = strlen((char*)S+1); +void derive_kseaf(uint8_t kausf[32], uint8_t kseaf[32], uicc_t *uicc) +{ + uint8_t S[100] = {0}; + S[0] = 0x6C; // FC + servingNetworkName(S + 1, uicc->imsiStr, uicc->nmc_size); + int netNamesize = strlen((char *)S + 1); S[1 + netNamesize] = (uint8_t)((netNamesize & 0xff00) >> 8); S[2 + netNamesize] = (uint8_t)(netNamesize & 0x00ff); - byte_array_t data = {.buf = S , .len = 3 + netNamesize}; + byte_array_t data = {.buf = S, .len = 3 + netNamesize}; kdf(kausf, data, 32, kseaf); } -void derive_kamf(uint8_t *kseaf, uint8_t *kamf, uint16_t abba, uicc_t* uicc) { +void derive_kamf(uint8_t *kseaf, uint8_t *kamf, uint16_t abba, uicc_t *uicc) +{ int imsiLen = strlen(uicc->imsiStr); uint8_t S[100] = {0}; - S[0] = 0x6D; //FC = 0x6D - memcpy(&S[1], uicc->imsiStr, imsiLen ); + S[0] = 0x6D; // FC = 0x6D + memcpy(&S[1], uicc->imsiStr, imsiLen); S[1 + imsiLen] = (uint8_t)((imsiLen & 0xff00) >> 8); S[2 + imsiLen] = (uint8_t)(imsiLen & 0x00ff); S[3 + imsiLen] = abba & 0x00ff; @@ -377,8 +380,8 @@ void derive_kamf(uint8_t *kseaf, uint8_t *kamf, uint16_t abba, uicc_t* uicc) { void derive_knas(algorithm_type_dist_t nas_alg_type, uint8_t nas_alg_id, uint8_t kamf[32], uint8_t *knas) { uint8_t S[20] = {0}; - uint8_t out[32] = { 0 }; - S[0] = 0x69; //FC + uint8_t out[32] = {0}; + S[0] = 0x69; // FC S[1] = (uint8_t)(nas_alg_type & 0xFF); S[2] = 0x00; S[3] = 0x01; @@ -389,14 +392,15 @@ void derive_knas(algorithm_type_dist_t nas_alg_type, uint8_t nas_alg_id, uint8_t byte_array_t data = {.buf = S, .len = 7}; kdf(kamf, data, 32, out); - memcpy(knas, out+16, 16); + memcpy(knas, out + 16, 16); } -void derive_kgnb(uint8_t kamf[32], uint32_t count, uint8_t *kgnb){ +void derive_kgnb(uint8_t kamf[32], uint32_t count, uint8_t *kgnb) +{ /* Compute the KDF input parameter * S = FC(0x6E) || UL NAS Count || 0x00 0x04 || 0x01 || 0x00 0x01 */ - uint8_t input[32] = {0}; + uint8_t input[32] = {0}; // uint16_t length = 4; // int offset = 0; @@ -421,12 +425,13 @@ void derive_kgnb(uint8_t kamf[32], uint32_t count, uint8_t *kgnb){ kdf(kamf, data, 32, kgnb); printf("kgnb : "); - for(int pp=0;pp<32;pp++) - printf("%02x ",kgnb[pp]); + for (int pp = 0; pp < 32; pp++) + printf("%02x ", kgnb[pp]); printf("\n"); } -void derive_ue_keys(uint8_t *buf, nr_ue_nas_t *nas) { +void derive_ue_keys(uint8_t *buf, nr_ue_nas_t *nas) +{ uint8_t ak[6]; uint8_t sqn[6]; @@ -439,8 +444,8 @@ void derive_ue_keys(uint8_t *buf, nr_ue_nas_t *nas) { uint8_t *kgnb = nas->security.kgnb; // get RAND for authentication request - for(int index = 0; index < 16;index++){ - rand[index] = buf[8+index]; + for (int index = 0; index < 16; index++) { + rand[index] = buf[8 + index]; } uint8_t resTemp[16]; @@ -449,30 +454,30 @@ void derive_ue_keys(uint8_t *buf, nr_ue_nas_t *nas) { transferRES(ck, ik, resTemp, rand, output, nas->uicc); - for(int index = 0; index < 6; index++){ - sqn[index] = buf[26+index]; + for (int index = 0; index < 6; index++) { + sqn[index] = buf[26 + index]; } derive_kausf(ck, ik, sqn, kausf, nas->uicc); derive_kseaf(kausf, kseaf, nas->uicc); derive_kamf(kseaf, kamf, 0x0000, nas->uicc); - derive_kgnb(kamf,0,kgnb); + derive_kgnb(kamf, 0, kgnb); printf("kausf:"); - for(int i = 0; i < 32; i++){ + for (int i = 0; i < 32; i++) { printf("%x ", kausf[i]); } printf("\n"); printf("kseaf:"); - for(int i = 0; i < 32; i++){ + for (int i = 0; i < 32; i++) { printf("%x ", kseaf[i]); } printf("\n"); printf("kamf:"); - for(int i = 0; i < 32; i++){ + for (int i = 0; i < 32; i++) { printf("%x ", kamf[i]); } printf("\n"); @@ -491,7 +496,7 @@ nr_ue_nas_t *get_ue_nas_info(module_id_t module_id) void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) { int size = sizeof(mm_msg_header_t); - fgs_nas_message_t nas_msg={0}; + fgs_nas_message_t nas_msg = {0}; MM_msg *mm_msg; mm_msg = &nas_msg.plain.mm_msg; @@ -500,7 +505,6 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) mm_msg->header.security_header_type = PLAIN_5GS_MSG; mm_msg->header.message_type = REGISTRATION_REQUEST; - // set registration request mm_msg->registration_request.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; size += 1; @@ -511,7 +515,7 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) mm_msg->registration_request.fgsregistrationtype = INITIAL_REGISTRATION; mm_msg->registration_request.naskeysetidentifier.naskeysetidentifier = 1; size += 1; - if(nas->guti){ + if (nas->guti) { size += fill_guti(&mm_msg->registration_request.fgsmobileidentity, nas->guti); } else { size += fill_suci(&mm_msg->registration_request.fgsmobileidentity, nas->uicc); @@ -542,12 +546,12 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) initialNasMsg->data = malloc16_clear(size * sizeof(Byte_t)); nas->registration_request_buf = initialNasMsg->data; - initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data), size); + initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t *)(initialNasMsg->data), size); nas->registration_request_len = initialNasMsg->length; - } -void generateIdentityResponse(as_nas_info_t *initialNasMsg, uint8_t identitytype, uicc_t* uicc) { +void generateIdentityResponse(as_nas_info_t *initialNasMsg, uint8_t identitytype, uicc_t *uicc) +{ int size = sizeof(mm_msg_header_t); fgs_nas_message_t nas_msg; memset(&nas_msg, 0, sizeof(fgs_nas_message_t)); @@ -559,7 +563,6 @@ void generateIdentityResponse(as_nas_info_t *initialNasMsg, uint8_t identitytype mm_msg->header.security_header_type = PLAIN_5GS_MSG; mm_msg->header.message_type = FGS_IDENTITY_RESPONSE; - // set identity response mm_msg->fgs_identity_response.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; size += 1; @@ -567,15 +570,14 @@ void generateIdentityResponse(as_nas_info_t *initialNasMsg, uint8_t identitytype size += 1; mm_msg->fgs_identity_response.messagetype = FGS_IDENTITY_RESPONSE; size += 1; - if(identitytype == FGS_MOBILE_IDENTITY_SUCI){ + if (identitytype == FGS_MOBILE_IDENTITY_SUCI) { size += fill_suci(&mm_msg->fgs_identity_response.fgsmobileidentity, uicc); } // encode the message initialNasMsg->data = (Byte_t *)malloc(size * sizeof(Byte_t)); - initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data), size); - + initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t *)(initialNasMsg->data), size); } static void generateAuthenticationResp(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, uint8_t *buf) @@ -583,7 +585,7 @@ static void generateAuthenticationResp(nr_ue_nas_t *nas, as_nas_info_t *initialN derive_ue_keys(buf, nas); OctetString res; res.length = 16; - res.value = calloc(1,16); + res.value = calloc(1, 16); memcpy(res.value, nas->security.res, 16); int size = sizeof(mm_msg_header_t); @@ -605,13 +607,13 @@ static void generateAuthenticationResp(nr_ue_nas_t *nas, as_nas_info_t *initialN mm_msg->fgs_identity_response.messagetype = FGS_AUTHENTICATION_RESPONSE; size += 1; - //set response parameter + // set response parameter mm_msg->fgs_auth_response.authenticationresponseparameter.res = res; size += 18; // encode the message initialNasMsg->data = (Byte_t *)malloc(size * sizeof(Byte_t)); - initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data), size); + initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t *)(initialNasMsg->data), size); } int nas_itti_kgnb_refresh_req(instance_t instance, const uint8_t kgnb[32]) @@ -630,7 +632,7 @@ static void generateSecurityModeComplete(nr_ue_nas_t *nas, as_nas_info_t *initia MM_msg *mm_msg; nas_stream_cipher_t stream_cipher; - uint8_t mac[4]; + uint8_t mac[4]; // set security protected header nas_msg.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; nas_msg.header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX; @@ -647,51 +649,53 @@ static void generateSecurityModeComplete(nr_ue_nas_t *nas, as_nas_info_t *initia // set security mode complete mm_msg->fgs_security_mode_complete.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; size += 1; - mm_msg->fgs_security_mode_complete.securityheadertype = PLAIN_5GS_MSG; + mm_msg->fgs_security_mode_complete.securityheadertype = PLAIN_5GS_MSG; size += 1; - mm_msg->fgs_security_mode_complete.messagetype = FGS_SECURITY_MODE_COMPLETE; + mm_msg->fgs_security_mode_complete.messagetype = FGS_SECURITY_MODE_COMPLETE; size += 1; size += fill_imeisv(&mm_msg->fgs_security_mode_complete.fgsmobileidentity, nas->uicc); - mm_msg->fgs_security_mode_complete.fgsnasmessagecontainer.nasmessagecontainercontents.value = nas->registration_request_buf; + mm_msg->fgs_security_mode_complete.fgsnasmessagecontainer.nasmessagecontainercontents.value = nas->registration_request_buf; mm_msg->fgs_security_mode_complete.fgsnasmessagecontainer.nasmessagecontainercontents.length = nas->registration_request_len; size += (nas->registration_request_len + 2); // encode the message initialNasMsg->data = (Byte_t *)malloc(size * sizeof(Byte_t)); - int security_header_len = nas_protected_security_header_encode((char*)(initialNasMsg->data),&(nas_msg.header), size); + int security_header_len = nas_protected_security_header_encode((char *)(initialNasMsg->data), &(nas_msg.header), size); - initialNasMsg->length = security_header_len + mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data+security_header_len), size-security_header_len); + initialNasMsg->length = + security_header_len + + mm_msg_encode(mm_msg, (uint8_t *)(initialNasMsg->data + security_header_len), size - security_header_len); /* ciphering */ uint8_t buf[initialNasMsg->length - 7]; - stream_cipher.context = nas->security_container->ciphering_context; + stream_cipher.context = nas->security_container->ciphering_context; AssertFatal(nas->security.nas_count_ul <= 0xffffff, "fatal: NAS COUNT UL too big (todo: fix that)\n"); - stream_cipher.count = nas->security.nas_count_ul; - stream_cipher.bearer = 1; - stream_cipher.direction = 0; - stream_cipher.message = (unsigned char *)(initialNasMsg->data + 7); + stream_cipher.count = nas->security.nas_count_ul; + stream_cipher.bearer = 1; + stream_cipher.direction = 0; + stream_cipher.message = (unsigned char *)(initialNasMsg->data + 7); /* length in bits */ - stream_cipher.blength = (initialNasMsg->length - 7) << 3; + stream_cipher.blength = (initialNasMsg->length - 7) << 3; stream_compute_encrypt(nas->security_container->ciphering_algorithm, &stream_cipher, buf); memcpy(stream_cipher.message, buf, initialNasMsg->length - 7); /* integrity protection */ - stream_cipher.context = nas->security_container->integrity_context; - stream_cipher.count = nas->security.nas_count_ul++; - stream_cipher.bearer = 1; - stream_cipher.direction = 0; - stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6); + stream_cipher.context = nas->security_container->integrity_context; + stream_cipher.count = nas->security.nas_count_ul++; + stream_cipher.bearer = 1; + stream_cipher.direction = 0; + stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6); /* length in bits */ - stream_cipher.blength = (initialNasMsg->length - 6) << 3; + stream_cipher.blength = (initialNasMsg->length - 6) << 3; stream_compute_integrity(nas->security_container->integrity_algorithm, &stream_cipher, mac); printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]); - for(int i = 0; i < 4; i++){ - initialNasMsg->data[2+i] = mac[i]; + for (int i = 0; i < 4; i++) { + initialNasMsg->data[2 + i] = mac[i]; } } @@ -711,13 +715,13 @@ static void handle_security_mode_command(nr_ue_nas_t *nas, as_nas_info_t *initia derive_knas(0x02, integrity_algorithm, kamf, knas_int); printf("knas_int: "); - for(int i = 0; i < 16; i++){ + for (int i = 0; i < 16; i++) { printf("%x ", knas_int[i]); } printf("\n"); printf("knas_enc: "); - for(int i = 0; i < 16; i++){ + for (int i = 0; i < 16; i++) { printf("%x ", knas_enc[i]); } printf("\n"); @@ -741,44 +745,46 @@ static void decodeRegistrationAccept(const uint8_t *buf, int len, nr_ue_nas_t *n int decoded = decode_registration_accept(®_acc, buf, len); AssertFatal(decoded > 0, "could not decode registration accept\n"); if (reg_acc.guti) { - AssertFatal(reg_acc.guti->guti.typeofidentity == FGS_MOBILE_IDENTITY_5G_GUTI, - "registration accept 5GS Mobile Identity is not GUTI, but %d\n", - reg_acc.guti->guti.typeofidentity); - nas->guti = malloc(sizeof(*nas->guti)); - AssertFatal(nas->guti, "out of memory\n"); - *nas->guti = reg_acc.guti->guti; - free(reg_acc.guti); /* no proper memory management for NAS decoded messages */ + AssertFatal(reg_acc.guti->guti.typeofidentity == FGS_MOBILE_IDENTITY_5G_GUTI, + "registration accept 5GS Mobile Identity is not GUTI, but %d\n", + reg_acc.guti->guti.typeofidentity); + nas->guti = malloc(sizeof(*nas->guti)); + AssertFatal(nas->guti, "out of memory\n"); + *nas->guti = reg_acc.guti->guti; + free(reg_acc.guti); /* no proper memory management for NAS decoded messages */ } else { LOG_W(NAS, "no GUTI in registration accept\n"); } } -static void generateRegistrationComplete(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, SORTransparentContainer *sortransparentcontainer) +static void generateRegistrationComplete(nr_ue_nas_t *nas, + as_nas_info_t *initialNasMsg, + SORTransparentContainer *sortransparentcontainer) { int length = 0; int size = 0; fgs_nas_message_t nas_msg; nas_stream_cipher_t stream_cipher; - uint8_t mac[4]; + uint8_t mac[4]; memset(&nas_msg, 0, sizeof(fgs_nas_message_t)); fgs_nas_message_security_protected_t *sp_msg; sp_msg = &nas_msg.security_protected; // set header sp_msg->header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - sp_msg->header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED; + sp_msg->header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED; sp_msg->header.message_authentication_code = 0; - sp_msg->header.sequence_number = nas->security.nas_count_ul & 0xff; + sp_msg->header.sequence_number = nas->security.nas_count_ul & 0xff; length = 7; sp_msg->plain.mm_msg.registration_complete.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; length += 1; - sp_msg->plain.mm_msg.registration_complete.securityheadertype = PLAIN_5GS_MSG; - sp_msg->plain.mm_msg.registration_complete.sparehalfoctet = 0; + sp_msg->plain.mm_msg.registration_complete.securityheadertype = PLAIN_5GS_MSG; + sp_msg->plain.mm_msg.registration_complete.sparehalfoctet = 0; length += 1; sp_msg->plain.mm_msg.registration_complete.messagetype = REGISTRATION_COMPLETE; length += 1; - if(sortransparentcontainer) { + if (sortransparentcontainer) { length += sortransparentcontainer->sortransparentcontainercontents.length; } @@ -788,62 +794,62 @@ static void generateRegistrationComplete(nr_ue_nas_t *nas, as_nas_info_t *initia /* Encode the first octet of the header (extended protocol discriminator) */ ENCODE_U8(initialNasMsg->data + size, sp_msg->header.protocol_discriminator, size); - + /* Encode the security header type */ ENCODE_U8(initialNasMsg->data + size, sp_msg->header.security_header_type, size); - + /* Encode the message authentication code */ ENCODE_U32(initialNasMsg->data + size, sp_msg->header.message_authentication_code, size); - + /* Encode the sequence number */ ENCODE_U8(initialNasMsg->data + size, sp_msg->header.sequence_number, size); - - + /* Encode the extended protocol discriminator */ ENCODE_U8(initialNasMsg->data + size, sp_msg->plain.mm_msg.registration_complete.protocoldiscriminator, size); - + /* Encode the security header type */ ENCODE_U8(initialNasMsg->data + size, sp_msg->plain.mm_msg.registration_complete.securityheadertype, size); - + /* Encode the message type */ ENCODE_U8(initialNasMsg->data + size, sp_msg->plain.mm_msg.registration_complete.messagetype, size); - if(sortransparentcontainer) { + if (sortransparentcontainer) { encode_registration_complete(&sp_msg->plain.mm_msg.registration_complete, initialNasMsg->data + size, length - size); } /* ciphering */ uint8_t buf[initialNasMsg->length - 7]; - stream_cipher.context = nas->security_container->ciphering_context; + stream_cipher.context = nas->security_container->ciphering_context; AssertFatal(nas->security.nas_count_ul <= 0xffffff, "fatal: NAS COUNT UL too big (todo: fix that)\n"); - stream_cipher.count = nas->security.nas_count_ul; - stream_cipher.bearer = 1; - stream_cipher.direction = 0; - stream_cipher.message = (unsigned char *)(initialNasMsg->data + 7); + stream_cipher.count = nas->security.nas_count_ul; + stream_cipher.bearer = 1; + stream_cipher.direction = 0; + stream_cipher.message = (unsigned char *)(initialNasMsg->data + 7); /* length in bits */ - stream_cipher.blength = (initialNasMsg->length - 7) << 3; + stream_cipher.blength = (initialNasMsg->length - 7) << 3; stream_compute_encrypt(nas->security_container->ciphering_algorithm, &stream_cipher, buf); memcpy(stream_cipher.message, buf, initialNasMsg->length - 7); /* integrity protection */ - stream_cipher.context = nas->security_container->integrity_context; - stream_cipher.count = nas->security.nas_count_ul++; - stream_cipher.bearer = 1; - stream_cipher.direction = 0; - stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6); + stream_cipher.context = nas->security_container->integrity_context; + stream_cipher.count = nas->security.nas_count_ul++; + stream_cipher.bearer = 1; + stream_cipher.direction = 0; + stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6); /* length in bits */ - stream_cipher.blength = (initialNasMsg->length - 6) << 3; + stream_cipher.blength = (initialNasMsg->length - 6) << 3; stream_compute_integrity(nas->security_container->integrity_algorithm, &stream_cipher, mac); printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]); - for(int i = 0; i < 4; i++){ - initialNasMsg->data[2+i] = mac[i]; + for (int i = 0; i < 4; i++) { + initialNasMsg->data[2 + i] = mac[i]; } } -void decodeDownlinkNASTransport(as_nas_info_t *initialNasMsg, uint8_t * pdu_buffer){ +void decodeDownlinkNASTransport(as_nas_info_t *initialNasMsg, uint8_t *pdu_buffer) +{ uint8_t msg_type = *(pdu_buffer + 16); - if(msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC){ + if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) { uint8_t *ip_p = pdu_buffer + 39; char ip[20]; sprintf(ip, "%d.%d.%d.%d", *(ip_p), *(ip_p + 1), *(ip_p + 2), *(ip_p + 3)); @@ -884,44 +890,46 @@ static void generateDeregistrationRequest(nr_ue_nas_t *nas, as_nas_info_t *initi initialNasMsg->data = calloc(size, sizeof(Byte_t)); int security_header_len = nas_protected_security_header_encode((char *)(initialNasMsg->data), &nas_msg.header, size); - initialNasMsg->length = security_header_len + mm_msg_encode(&sp_msg->plain.mm_msg, (uint8_t *)(initialNasMsg->data + security_header_len), size - security_header_len); + initialNasMsg->length = + security_header_len + + mm_msg_encode(&sp_msg->plain.mm_msg, (uint8_t *)(initialNasMsg->data + security_header_len), size - security_header_len); nas_stream_cipher_t stream_cipher; /* ciphering */ uint8_t buf[initialNasMsg->length - 7]; - stream_cipher.context = nas->security_container->ciphering_context; + stream_cipher.context = nas->security_container->ciphering_context; AssertFatal(nas->security.nas_count_ul <= 0xffffff, "fatal: NAS COUNT UL too big (todo: fix that)\n"); - stream_cipher.count = nas->security.nas_count_ul; - stream_cipher.bearer = 1; - stream_cipher.direction = 0; - stream_cipher.message = (unsigned char *)(initialNasMsg->data + 7); + stream_cipher.count = nas->security.nas_count_ul; + stream_cipher.bearer = 1; + stream_cipher.direction = 0; + stream_cipher.message = (unsigned char *)(initialNasMsg->data + 7); /* length in bits */ - stream_cipher.blength = (initialNasMsg->length - 7) << 3; + stream_cipher.blength = (initialNasMsg->length - 7) << 3; stream_compute_encrypt(nas->security_container->ciphering_algorithm, &stream_cipher, buf); memcpy(stream_cipher.message, buf, initialNasMsg->length - 7); /* integrity protection */ - stream_cipher.context = nas->security_container->integrity_context; - stream_cipher.count = nas->security.nas_count_ul++; - stream_cipher.bearer = 1; - stream_cipher.direction = 0; - stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6); + stream_cipher.context = nas->security_container->integrity_context; + stream_cipher.count = nas->security.nas_count_ul++; + stream_cipher.bearer = 1; + stream_cipher.direction = 0; + stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6); /* length in bits */ - stream_cipher.blength = (initialNasMsg->length - 6) << 3; + stream_cipher.blength = (initialNasMsg->length - 6) << 3; uint8_t mac[4]; stream_compute_integrity(nas->security_container->integrity_algorithm, &stream_cipher, mac); printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]); - for(int i = 0; i < 4; i++){ - initialNasMsg->data[2+i] = mac[i]; + for (int i = 0; i < 4; i++) { + initialNasMsg->data[2 + i] = mac[i]; } } static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, nas_pdu_session_req_t *pdu_req) { int size = 0; - fgs_nas_message_t nas_msg={0}; + fgs_nas_message_t nas_msg = {0}; // setup pdu session establishment request uint16_t req_length = 7; @@ -935,11 +943,9 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t * pdu_session_establish.pdusessiontype = pdu_req->pdusession_type; encode_pdu_session_establishment_request(&pdu_session_establish, req_buffer); - - MM_msg *mm_msg; nas_stream_cipher_t stream_cipher; - uint8_t mac[4]; + uint8_t mac[4]; nas_msg.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; nas_msg.header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED; nas_msg.header.sequence_number = nas->security.nas_count_ul & 0xff; @@ -956,7 +962,7 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t * // set uplink nas transport mm_msg->uplink_nas_transport.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; size += 1; - mm_msg->uplink_nas_transport.securityheadertype = PLAIN_5GS_MSG; + mm_msg->uplink_nas_transport.securityheadertype = PLAIN_5GS_MSG; size += 1; mm_msg->uplink_nas_transport.messagetype = FGS_UPLINK_NAS_TRANSPORT; size += 1; @@ -966,64 +972,65 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t * size += 1; mm_msg->uplink_nas_transport.fgspayloadcontainer.payloadcontainercontents.length = req_length; mm_msg->uplink_nas_transport.fgspayloadcontainer.payloadcontainercontents.value = req_buffer; - size += (2+req_length); + size += (2 + req_length); mm_msg->uplink_nas_transport.pdusessionid = pdu_req->pdusession_id; mm_msg->uplink_nas_transport.requesttype = 1; size += 3; const bool has_nssai_sd = pdu_req->sd != 0xffffff; // 0xffffff means "no SD", TS 23.003 const size_t nssai_len = has_nssai_sd ? 4 : 1; mm_msg->uplink_nas_transport.snssai.length = nssai_len; - //Fixme: it seems there are a lot of memory errors in this: this value was on the stack, - // but pushed in a itti message to another thread - // this kind of error seems in many places in 5G NAS + // Fixme: it seems there are a lot of memory errors in this: this value was on the stack, + // but pushed in a itti message to another thread + // this kind of error seems in many places in 5G NAS mm_msg->uplink_nas_transport.snssai.value = calloc(1, nssai_len); mm_msg->uplink_nas_transport.snssai.value[0] = pdu_req->sst; if (has_nssai_sd) INT24_TO_BUFFER(pdu_req->sd, &mm_msg->uplink_nas_transport.snssai.value[1]); size += 1 + 1 + nssai_len; - int dnnSize=strlen(nas->uicc->dnnStr); - mm_msg->uplink_nas_transport.dnn.value=calloc(1,dnnSize+1); + int dnnSize = strlen(nas->uicc->dnnStr); + mm_msg->uplink_nas_transport.dnn.value = calloc(1, dnnSize + 1); mm_msg->uplink_nas_transport.dnn.length = dnnSize + 1; mm_msg->uplink_nas_transport.dnn.value[0] = dnnSize; memcpy(mm_msg->uplink_nas_transport.dnn.value + 1, nas->uicc->dnnStr, dnnSize); - size += (1+1+dnnSize+1); + size += (1 + 1 + dnnSize + 1); // encode the message initialNasMsg->data = (Byte_t *)malloc(size * sizeof(Byte_t)); - int security_header_len = nas_protected_security_header_encode((char*)(initialNasMsg->data),&(nas_msg.header), size); + int security_header_len = nas_protected_security_header_encode((char *)(initialNasMsg->data), &(nas_msg.header), size); - initialNasMsg->length = security_header_len + mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data+security_header_len), size-security_header_len); + initialNasMsg->length = + security_header_len + + mm_msg_encode(mm_msg, (uint8_t *)(initialNasMsg->data + security_header_len), size - security_header_len); /* ciphering */ uint8_t buf[initialNasMsg->length - 7]; - stream_cipher.context = nas->security_container->ciphering_context; + stream_cipher.context = nas->security_container->ciphering_context; AssertFatal(nas->security.nas_count_ul <= 0xffffff, "fatal: NAS COUNT UL too big (todo: fix that)\n"); - stream_cipher.count = nas->security.nas_count_ul; - stream_cipher.bearer = 1; - stream_cipher.direction = 0; - stream_cipher.message = (unsigned char *)(initialNasMsg->data + 7); + stream_cipher.count = nas->security.nas_count_ul; + stream_cipher.bearer = 1; + stream_cipher.direction = 0; + stream_cipher.message = (unsigned char *)(initialNasMsg->data + 7); /* length in bits */ - stream_cipher.blength = (initialNasMsg->length - 7) << 3; + stream_cipher.blength = (initialNasMsg->length - 7) << 3; stream_compute_encrypt(nas->security_container->ciphering_algorithm, &stream_cipher, buf); memcpy(stream_cipher.message, buf, initialNasMsg->length - 7); /* integrity protection */ - stream_cipher.context = nas->security_container->integrity_context; - stream_cipher.count = nas->security.nas_count_ul++; - stream_cipher.bearer = 1; - stream_cipher.direction = 0; - stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6); + stream_cipher.context = nas->security_container->integrity_context; + stream_cipher.count = nas->security.nas_count_ul++; + stream_cipher.bearer = 1; + stream_cipher.direction = 0; + stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6); /* length in bits */ - stream_cipher.blength = (initialNasMsg->length - 6) << 3; + stream_cipher.blength = (initialNasMsg->length - 6) << 3; stream_compute_integrity(nas->security_container->integrity_algorithm, &stream_cipher, mac); printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]); - for(int i = 0; i < 4; i++){ - initialNasMsg->data[2+i] = mac[i]; + for (int i = 0; i < 4; i++) { + initialNasMsg->data[2 + i] = mac[i]; } } - static uint8_t get_msg_type(uint8_t *pdu_buffer, uint32_t length) { if (pdu_buffer == NULL) @@ -1066,7 +1073,7 @@ static void send_nas_uplink_data_req(nr_ue_nas_t *nas, const as_nas_info_t *init MessageDef *msg = itti_alloc_new_message(TASK_NAS_NRUE, nas->UE_id, NAS_UPLINK_DATA_REQ); ul_info_transfer_req_t *req = &NAS_UPLINK_DATA_REQ(msg); req->UEid = nas->UE_id; - req->nasMsg.data = (uint8_t *) initial_nas_msg->data; + req->nasMsg.data = (uint8_t *)initial_nas_msg->data; req->nasMsg.length = initial_nas_msg->length; itti_send_msg_to_task(TASK_RRC_NRUE, nas->UE_id, msg); } @@ -1207,9 +1214,7 @@ void *nas_nrue_task(void *args_p) } } -static void handle_registration_accept(nr_ue_nas_t *nas, - const uint8_t *pdu_buffer, - uint32_t msg_length) +static void handle_registration_accept(nr_ue_nas_t *nas, const uint8_t *pdu_buffer, uint32_t msg_length) { LOG_I(NAS, "[UE] Received REGISTRATION ACCEPT message\n"); decodeRegistrationAccept(pdu_buffer, msg_length, nas); @@ -1305,8 +1310,7 @@ void *nas_nrue(void *args_p) int pdu_length = NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length; security_state_t security_state = nas_security_rx_process(nas, pdu_buffer, pdu_length); - if (security_state != NAS_SECURITY_INTEGRITY_PASSED - && security_state != NAS_SECURITY_NO_SECURITY_CONTEXT) { + if (security_state != NAS_SECURITY_INTEGRITY_PASSED && security_state != NAS_SECURITY_NO_SECURITY_CONTEXT) { LOG_E(NAS, "NAS integrity failed, discard incoming message\n"); break; } @@ -1323,8 +1327,7 @@ void *nas_nrue(void *args_p) } 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); + 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); // TODO handle connection release if (nas->termination_procedure) { /* the following is not clean, but probably necessary: we need to give @@ -1385,8 +1388,7 @@ void *nas_nrue(void *args_p) security_state = NAS_SECURITY_INTEGRITY_PASSED; } - if (security_state != NAS_SECURITY_INTEGRITY_PASSED - && security_state != NAS_SECURITY_NO_SECURITY_CONTEXT) { + if (security_state != NAS_SECURITY_INTEGRITY_PASSED && security_state != NAS_SECURITY_NO_SECURITY_CONTEXT) { LOG_E(NAS, "NAS integrity failed, discard incoming message\n"); break; } @@ -1438,9 +1440,9 @@ void *nas_nrue(void *args_p) offset++; } } break; - case FGS_PDU_SESSION_ESTABLISHMENT_REJ: - LOG_E(NAS, "Received PDU Session Establishment reject\n"); - break; + case FGS_PDU_SESSION_ESTABLISHMENT_REJ: + LOG_E(NAS, "Received PDU Session Establishment reject\n"); + break; default: LOG_W(NR_RRC, "unknown message type %d\n", msg_type); break; From bac4f798f9bb2a4719efbd75f11e17036ceae4ba Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 23 Aug 2024 11:23:07 +0200 Subject: [PATCH 12/23] Fix misalignment issues in TLVEncoder macros ENCODE_U16, ENCODE_U24 This commit resolves undefined behaviour runtime errors related to misaligned memory access. E.g. > openair3/NAS/COMMON/IES/FGSMobileIdentity.c:193:3: > runtime error: store to misaligned address 0x608000021e2b for type 'uint16_t', > which requires 2 byte alignment 0x608000021e2b: note: pointer points here 00 f1 ... * ENCODE_U24: safely encode 24-bit values into a buffer by using memcpy to copy 3 bytes in network byte order (big-endian). * ENCODE_U16: safely encodes a 16-bit value into a buffer, handling misalignment by memcpy 2 bytes to buffer in network byte order (big-endian). --- openair3/NAS/COMMON/UTIL/TLVEncoder.h | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/openair3/NAS/COMMON/UTIL/TLVEncoder.h b/openair3/NAS/COMMON/UTIL/TLVEncoder.h index cd63a3d315..8080afbd5f 100644 --- a/openair3/NAS/COMMON/UTIL/TLVEncoder.h +++ b/openair3/NAS/COMMON/UTIL/TLVEncoder.h @@ -28,13 +28,25 @@ *(uint8_t*)(buffer) = value; \ size += sizeof(uint8_t) -#define ENCODE_U16(buffer, value, size) \ - *(uint16_t*)(buffer) = htons(value); \ - size += sizeof(uint16_t) +/* Safely encodes a 16-bit value into a buffer, handling + misalignment by memcpy 2 bytes to buffer in network + byte order (big-endian). */ +#define ENCODE_U16(buffer, value, size) \ + do { \ + uint16_t _val = htons(value); \ + memcpy((buffer), &_val, sizeof(uint16_t)); \ + size += sizeof(uint16_t); \ + } while (0) -#define ENCODE_U24(buffer, value, size) \ - *(uint32_t*)(buffer) = htonl(value); \ - size += sizeof(uint8_t) + sizeof(uint16_t) +/* Safely encodes a 24-bit value into a buffer, handling + misalignment by using htonl and memcpy to copy 3 bytes + in network byte order (big-endian). */ +#define ENCODE_U24(buffer, value, size) \ + do { \ + uint32_t _val = htonl(value); \ + memcpy((buffer), ((uint8_t*)&_val) + 1, 3); \ + size += sizeof(uint8_t) + sizeof(uint16_t); \ + } while (0) #define ENCODE_U32(buffer, value, size) \ { \ From 0eb409f1149ab3c58d5e9cdc7a2dc3e8ea95f31b Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 1 Aug 2024 13:48:24 +0200 Subject: [PATCH 13/23] NR_UE: Perform autonomous timing advance to compensate for fast time drift with relatively large RTT As we don't have SIB19 with continuously updated ta-Common and ta-CommonDrift values yet, the UE can only adapt it's UL timing according to it's DL drift. This is required for the UE to keep UL sync with fast time drift and relatively long RTT (e.g. LEO satellite). We should replace this with the standard compliant way as soon as we have SIB19 with continuously updated contents. --- executables/nr-softmodem-common.h | 1 - executables/nr-ue.c | 6 ++++++ executables/nr-uesoftmodem.h | 6 +++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h index 205cd6072b..714d885a16 100644 --- a/executables/nr-softmodem-common.h +++ b/executables/nr-softmodem-common.h @@ -98,7 +98,6 @@ #define CONFIG_HLP_TELN "Start embedded telnet server \n" #define CONFIG_HLP_SNR "Set average SNR in dB (for --siml1 option)\n" #define CONFIG_HLP_NOS1 "Disable s1 interface\n" -#define CONFIG_HLP_AGC "Rx Gain control used for UE" /*--------------------------------------------------------------------------------------------------------------------------------*/ /* command line parameters for LOG utility */ diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 9eafacee52..631c270ca1 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -889,6 +889,9 @@ void *UE_thread(void *arg) UE->max_pos_acc = get_nrUE_params()->ntn_ta_commondrift * 1e-6 * fp->samples_per_frame / get_nrUE_params()->time_sync_I; // ntn_ta_commondrift is in µs/s, max_pos_acc * time_sync_I is in samples/frame shiftForNextFrame = -(UE->init_sync_frame + trashed_frames + 2) * UE->max_pos_acc * get_nrUE_params()->time_sync_I; // compensate for the time drift that happened during initial sync LOG_D(PHY, "max_pos_acc = %d, shiftForNextFrame = %d\n", UE->max_pos_acc, shiftForNextFrame); + // TODO: remove this autonomous TA and use up-to-date values of ta-Common, ta-CommonDrift and ta-CommonDriftVariant from received SIB19 instead + if (get_nrUE_params()->autonomous_ta) + UE->timing_advance -= 2 * shiftForNextFrame; // read in first symbol AssertFatal(fp->ofdm_symbol_size + fp->nb_prefix_samples0 == UE->rfdevice.trx_read_func(&UE->rfdevice, @@ -949,6 +952,9 @@ void *UE_thread(void *arg) if (slot_nr == nb_slot_frame - 1) { // we shift of half of measured drift, at each beginning of frame for both rx and tx iq_shift_to_apply = shiftForNextFrame; + // TODO: remove this autonomous TA and use up-to-date values of ta-Common, ta-CommonDrift and ta-CommonDriftVariant from received SIB19 instead + if (get_nrUE_params()->autonomous_ta) + UE->timing_advance -= 2 * shiftForNextFrame; shiftForNextFrame = -round(UE->max_pos_acc * get_nrUE_params()->time_sync_I); } diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 5b745cec61..5fe68ed60f 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -14,6 +14,8 @@ #define CONFIG_HLP_NTN_KOFFSET "NTN cellSpecificKoffset-r17 (number of slots for a given subcarrier spacing of 15 kHz)\n" #define CONFIG_HLP_NTN_TA_COMMON "NTN ta-Common, but given in ms\n" #define CONFIG_HLP_NTN_TA_COMMONDRIFT "NTN ta-CommonDrift, but given in µs/s\n" +#define CONFIG_HLP_AUTONOMOUS_TA "Autonomously update TA based on DL drift (useful if main contribution to DL drift is movement, e.g. LEO satellite)\n" +#define CONFIG_HLP_AGC "Rx Gain control used for UE\n" /***************************************************************************************************************************************/ /* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument @@ -67,7 +69,8 @@ {"ntn-koffset", CONFIG_HLP_NTN_KOFFSET, 0, .uptr=&(nrUE_params.ntn_koffset), .defuintval=0, TYPE_UINT, 0}, \ {"ntn-ta-common", CONFIG_HLP_NTN_TA_COMMON, 0, .dblptr=&(nrUE_params.ntn_ta_common), .defdblval=0.0, TYPE_DOUBLE, 0}, \ {"ntn-ta-commondrift", CONFIG_HLP_NTN_TA_COMMONDRIFT, 0, .dblptr=&(nrUE_params.ntn_ta_commondrift), .defdblval=0.0, TYPE_DOUBLE, 0}, \ - {"agc", CONFIG_HLP_AGC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.agc), .defintval=0, TYPE_INT, 0}, \ + {"autonomous-ta", CONFIG_HLP_AUTONOMOUS_TA, PARAMFLAG_BOOL, .iptr=&(nrUE_params.autonomous_ta), .defintval=0, TYPE_INT, 0}, \ + {"agc", CONFIG_HLP_AGC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.agc), .defintval=0, TYPE_INT, 0}, \ } // clang-format on @@ -93,6 +96,7 @@ typedef struct { unsigned int ntn_koffset; double ntn_ta_common; double ntn_ta_commondrift; + int autonomous_ta; int agc; char *usrp_args; char *tx_subdev; From ede6775ac3f8493ebdbedcf2c7cff8fc84101620 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 1 Aug 2024 17:19:38 +0200 Subject: [PATCH 14/23] fix for compilers that don't support the CMPLX() macro --- radio/rfsimulator/apply_channelmod.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/radio/rfsimulator/apply_channelmod.c b/radio/rfsimulator/apply_channelmod.c index 5bb207e5be..dc35a9bf73 100644 --- a/radio/rfsimulator/apply_channelmod.c +++ b/radio/rfsimulator/apply_channelmod.c @@ -166,7 +166,11 @@ void rxAddInput(const c16_t *input_sig, } if (channelDesc->Doppler_phase_inc != 0.0) { +#ifdef CMPLX double complex in = CMPLX(rx_tmp.r, rx_tmp.i); +#else + double complex in = rx_tmp.r + rx_tmp.i * I; +#endif double complex out = in * cexp(channelDesc->Doppler_phase_cur[rxAnt] * I); rx_tmp.r = creal(out); rx_tmp.i = cimag(out); From b17b44dffb2828ea8b2d042f189ca93e7e916df1 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 8 Aug 2024 12:22:41 +0200 Subject: [PATCH 15/23] add description how to run a LEO satellite rfsimulation to RUNMODEM.md --- doc/RUNMODEM.md | 70 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index 928935f898..378fe3be16 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -157,6 +157,42 @@ E.g. to perform a simple simulation of a satellite in geostationary orbit (GEO), --rfsimulator.prop_delay 238.74 ``` +For simulation of a satellite in low earth orbit (LEO), two channel models have been added to rfsimulator: +- `SAT_LEO_TRANS`: transparent LEO satellite with gNB on ground +- `SAT_LEO_REGEN`: regenerative LEO satellite with gNB on board + +Both channel models simulate the delay and Doppler for a circular orbit at 600 km height according to the Matlab function [dopplerShiftCircularOrbit](https://de.mathworks.com/help/satcom/ref/dopplershiftcircularorbit.html). +An example configuration to simulate a transparent LEO satellite with rfsimulator would be: +``` +channelmod = { + max_chan=10; + modellist="modellist_rfsimu_1"; + modellist_rfsimu_1 = ( + { + model_name = "rfsimu_channel_enB0" + type = "SAT_LEO_TRANS"; + noise_power_dB = -100; + }, + { + model_name = "rfsimu_channel_ue0" + type = "SAT_LEO_TRANS"; + noise_power_dB = -100; + } + ); +}; +``` +This configuration is also provided in the file `targets/PROJECTS/GENERIC-NR-5GC/CONF/channelmod_rfsimu_LEO_satellite.conf`. + +Additionally, rfsimulator has to be configured to apply the channel model. +This can be done by either providing this line in the conf file in section `rfsimulator`: +``` + options = ("chanmod"); +``` +Or by providing this the the command line parameters: +``` +--rfsimulator.options chanmod +``` + ### gNB The main parameter to cope with the large NTN propagation delay is the cellSpecificKoffset. @@ -166,11 +202,12 @@ The unit of the field Koffset is number of slots for a given subcarrier spacing This parameter can be provided to the gNB in the conf file as `cellSpecificKoffset_r17` in the section `servingCellConfigCommon`. ``` ... - cellSpecificKoffset_r17 = 478; + cellSpecificKoffset_r17 = 478; # GEO satellite +# cellSpecificKoffset_r17 = 40; # LEO satellite ... ``` -Besides this, some timers, e.g. `sr_ProhibitTimer_v1700`, `t300`, `t301` and `t319`, in the conf file section `gNBs.[0].TIMERS` might need to be extended. +Besides this, some timers, e.g. `sr_ProhibitTimer_v1700`, `t300`, `t301` and `t319`, in the conf file section `gNBs.[0].TIMERS` might need to be extended for GEO satellites. ``` ... TIMERS : @@ -185,7 +222,7 @@ Besides this, some timers, e.g. `sr_ProhibitTimer_v1700`, `t300`, `t301` and `t3 ... ``` -To improve the achievable UL and DL throughput in conditions with large RTT, there is a feature defined in REL17 to disable HARQ feedback. +To improve the achievable UL and DL throughput in conditions with large RTT (esp. GEO satellites), there is a feature defined in REL17 to disable HARQ feedback. This allows to reuse HARQ processes immediately, but it breaks compatibility with UEs not supporting this REL17 feature. To enable this feature, the `disable_harq` flag has to be added to the gNB conf file in the section `gNBs.[0]` ``` @@ -199,7 +236,7 @@ To enable this feature, the `disable_harq` flag has to be added to the gNB conf ... ``` -So with these modifications to the file `targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf` an example gNB command for FDD, 5 MHz BW, 15 kHz SCS, GEO satellite 5G NR NTN is this: +So with these modifications to the file `targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf` an example gNB command for FDD, 5 MHz BW, 15 kHz SCS, transparent GEO satellite 5G NR NTN is this: ``` cd cmake_targets sudo ./ran_build/build/nr-softmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf --sa --rfsim --rfsimulator.prop_delay 238.74 @@ -213,18 +250,39 @@ To configure NTN gNB with 32 HARQ processes in downlink and uplink, add these se ... ``` +To simulate a LEO satellite channel model with rfsimulator in UL (DL is simulated at the UE side) either the `channelmod` section as shown before has to be added to the gNB conf file, or a channelmod conf file has to be included like this: +``` +@include "channelmod_rfsimu_LEO_satellite.conf" +``` + +So with these modifications to the file `targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf` an example gNB command for FDD, 5 MHz BW, 15 kHz SCS, trasparent LEO satellite 5G NR NTN is this: +``` +cd cmake_targets +sudo ./ran_build/build/nr-softmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf --sa --rfsim --rfsimulator.prop_delay 20 +``` + ### NR UE At UE side, there are two main parameters to cope with the large NTN propagation delay, cellSpecificKoffset and ta-Common. `cellSpecificKoffset` is the same as for gNB and can be provided to the UE via command line parameter `--ntn-koffset`. -`ta-Common` is a common timong advance and can be provided to the UE via command line parameter `--ntn-ta-common` in milliseconds. +`ta-Common` is a common timing advance and can be provided to the UE via command line parameter `--ntn-ta-common` in milliseconds. -So an example NR UE command for FDD, 5MHz BW, 15 kHz SCS, GEO satellite 5G NR NTN is this: +So an example NR UE command for FDD, 5MHz BW, 15 kHz SCS, transparent GEO satellite 5G NR NTN is this: ``` cd cmake_targets sudo ./ran_build/build/nr-uesoftmodem --band 66 -C 2152680000 --CO -400000000 -r 25 --numerology 0 --ssb 48 --sa --rfsim --rfsimulator.prop_delay 238.74 --ntn-koffset 478 --ntn-ta-common 477.48 ``` +For LEO satellites a third parameter specifying the NTN propagation delay drift has ben added, ta-CommonDrift. +`ta-CommonDrift` provides the drift rate of the common timing advance and can be provided to the UE via command line parameter `--ntn-ta-commondrift` in microseconds per second. +Also, to perform an autonomous TA update based on the DL drift, the boolean parameter `--autonomous-ta` should be added in case of a LEO satellite scenario. + +So an example NR UE command for FDD, 5MHz BW, 15 kHz SCS, transparent LEO satellite 5G NR NTN is this: +``` +cd cmake_targets +sudo ./ran_build/build/nr-uesoftmodem --band 66 -C 2152680000 --CO -400000000 -r 25 --numerology 0 --ssb 48 --sa --rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/channelmod_rfsimu_LEO_satellite.conf --ntn-koffset 40 --ntn-ta-common 37.74 --ntn-ta-commondrift -50 --autonomous-ta +``` + # Specific OAI modes ## phy-test setup with OAI UE From 9e6435758a4e52607b9c2709d0e6d47890ef7c68 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 26 Aug 2024 10:13:18 +0200 Subject: [PATCH 16/23] Wrap multi-statement macros ENCODE_U8() and ENCODE_U32() in do { ... } while (0) statements --- openair3/NAS/COMMON/UTIL/TLVEncoder.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/openair3/NAS/COMMON/UTIL/TLVEncoder.h b/openair3/NAS/COMMON/UTIL/TLVEncoder.h index 8080afbd5f..8b85185361 100644 --- a/openair3/NAS/COMMON/UTIL/TLVEncoder.h +++ b/openair3/NAS/COMMON/UTIL/TLVEncoder.h @@ -24,9 +24,11 @@ #include // htonl, htons -#define ENCODE_U8(buffer, value, size) \ - *(uint8_t*)(buffer) = value; \ - size += sizeof(uint8_t) +#define ENCODE_U8(buffer, value, size) \ + do { \ + *(uint8_t*)(buffer) = value; \ + size += sizeof(uint8_t); \ + } while (0) /* Safely encodes a 16-bit value into a buffer, handling misalignment by memcpy 2 bytes to buffer in network @@ -49,11 +51,11 @@ } while (0) #define ENCODE_U32(buffer, value, size) \ - { \ + do { \ uint32_t tmp = htonl(value); \ memcpy(buffer, &tmp, sizeof(tmp)); \ - } \ - size += sizeof(uint32_t) + size += sizeof(uint32_t); \ + } while (0) #define IES_ENCODE_U8(buffer, encoded, value) \ ENCODE_U8(buffer + encoded, value, encoded) From 4b859a2eb802ba8d40cf87605f950d0370771c18 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Mon, 26 Aug 2024 17:08:03 +0200 Subject: [PATCH 17/23] fix sidelink UE issues found by sanitizer --- executables/nr-ue.c | 4 ++-- openair2/LAYER2/NR_MAC_UE/mac_defs_sl.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index dca05ea36a..7d643e634e 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -802,7 +802,7 @@ void *UE_thread(void *arg) bool syncRunning = false; const int nb_slot_frame = fp->slots_per_frame; - int absolute_slot = 0, decoded_frame_rx = INT_MAX, trashed_frames = 0; + int absolute_slot = 0, decoded_frame_rx = MAX_FRAME_NUMBER - 1, trashed_frames = 0; int tx_wait_for_dlsch[NR_MAX_SLOTS_PER_FRAME]; int num_ind_fifo = nb_slot_frame; @@ -897,7 +897,7 @@ void *UE_thread(void *arg) ""); // we have the decoded frame index in the return of the synch process // and we shifted above to the first slot of next frame - decoded_frame_rx++; + decoded_frame_rx = (decoded_frame_rx + 1) % MAX_FRAME_NUMBER; // we do ++ first in the regular processing, so it will be begin of frame; absolute_slot = decoded_frame_rx * nb_slot_frame - 1; if (UE->sl_mode == 2) { diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs_sl.h b/openair2/LAYER2/NR_MAC_UE/mac_defs_sl.h index 5960a30a46..10eaea3862 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs_sl.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs_sl.h @@ -120,9 +120,9 @@ typedef struct sl_bch_params { //configured from RRC //Parameters used to determine PSBCH slot sl_ssb_timealloc_t ssb_time_alloc; + uint8_t sl_mib[4] __attribute__((aligned(4))); uint16_t slss_id; bool status; - uint8_t sl_mib[4]; //Parameters incremented by MAC PSBCH scheduler //after every SSB txn/reception From d9648ae6b2c03da899fcd533f7a4a294539186c6 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Wed, 7 Aug 2024 16:14:17 +0200 Subject: [PATCH 18/23] CI: Reduce ping time in rfsim 5G --- ci-scripts/xml_files/container_5g_fdd_rfsim.xml | 4 ++-- ci-scripts/xml_files/container_5g_rfsim.xml | 14 +++++++------- ci-scripts/xml_files/container_5g_rfsim_2x2.xml | 4 ++-- .../xml_files/container_5g_rfsim_u0_25prb.xml | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml index da059dadd4..92629a4700 100644 --- a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml @@ -72,7 +72,7 @@ Ping Ping ext-dn from NR-UE rfsim5g_ue - -c 20 192.168.72.135 + -c 20 -i 0.25 192.168.72.135 5 @@ -80,7 +80,7 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - -c 20 12.1.1.2 + -c 20 -i 0.25 12.1.1.2 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim.xml b/ci-scripts/xml_files/container_5g_rfsim.xml index e3779d3e6b..1709b4492d 100644 --- a/ci-scripts/xml_files/container_5g_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_rfsim.xml @@ -127,7 +127,7 @@ Ping Ping ext-dn from NR-UE rfsim5g_ue - -c 20 192.168.72.135 + -c 20 -i 0.25 192.168.72.135 5 @@ -135,7 +135,7 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - -c 20 12.1.1.2 + -c 20 -i 0.25 12.1.1.2 5 @@ -143,7 +143,7 @@ Ping Ping ext-dn from Second NR-UE rfsim5g_ue - -c 20 192.168.72.135 + -c 20 -i 0.25 192.168.72.135 5 @@ -151,7 +151,7 @@ Ping Ping Second NR-UE from ext-dn rfsim5g_ext_dn - -c 20 12.1.1.3 + -c 20 -i 0.25 12.1.1.3 5 @@ -159,7 +159,7 @@ Ping Ping ext-dn from both UEs rfsim5g_ue rfsim5g_ue2 - -c 20 192.168.72.135 + -c 20 -i 0.25 192.168.72.135 5 @@ -167,7 +167,7 @@ Ping Ping ext-dn from both UEs rfsim5g_ue rfsim5g_ue2 - -c 20 192.168.72.135 + -c 20 -i 0.25 192.168.72.135 5 @@ -175,7 +175,7 @@ Ping Ping ext-dn from all UEs rfsim5g_ue rfsim5g_ue2 rfsim5g_ue3 rfsim5g_ue4 rfsim5g_ue5 rfsim5g_ue6 rfsim5g_ue7 rfsim5g_ue8 rfsim5g_ue9 rfsim5g_ue10 - -c 100 192.168.72.135 -i 0.2 -s 1016 + -c 20 192.168.72.135 -i 0.25 -s 1016 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml index 7899ac00c7..9cc87f830d 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml @@ -72,7 +72,7 @@ Ping Ping ext-dn from NR-UE rfsim5g_ue - -c 20 192.168.72.135 + -c 20 -i 0.25 192.168.72.135 5 @@ -80,7 +80,7 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - -c 20 12.1.1.2 + -c 20 -i 0.25 12.1.1.2 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml index 0540d44f1f..964e1f6ac4 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml @@ -72,7 +72,7 @@ Ping Ping ext-dn from NR-UE rfsim5g_ue - -c 20 192.168.72.135 + -c 20 -i 0.25 192.168.72.135 5 @@ -80,7 +80,7 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - -c 20 12.1.1.2 + -c 20 -i 0.25 12.1.1.2 5 From 7293741a995720327dd8ec509a87a1b13ec02756 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 9 Aug 2024 22:22:42 +0200 Subject: [PATCH 19/23] CI: Reduce iperf time in RF-Sim 5G --- ci-scripts/xml_files/container_5g_f1_rfsim.xml | 4 ++-- ci-scripts/xml_files/container_5g_rfsim.xml | 4 ++-- ci-scripts/xml_files/container_5g_rfsim_24prb.xml | 4 ++-- ci-scripts/xml_files/container_5g_rfsim_2x2.xml | 4 ++-- ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml | 4 ++-- ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index 6c95796d87..be31c6202a 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -86,7 +86,7 @@ Iperf Iperf (DL/5Mbps/UDP)(30 sec) - -u -b 5M -t 30 -R + -u -b 5M -t 20 -R rfsim5g_ue rfsim5g_ext_dn 5 @@ -96,7 +96,7 @@ Iperf Iperf (UL/3Mbps/UDP)(30 sec) - -u -b 3M -t 30 + -u -b 3M -t 20 rfsim5g_ue rfsim5g_ext_dn 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim.xml b/ci-scripts/xml_files/container_5g_rfsim.xml index 1709b4492d..3751b256f2 100644 --- a/ci-scripts/xml_files/container_5g_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_rfsim.xml @@ -182,7 +182,7 @@ Iperf Iperf (DL/3Mbps/UDP)(30 sec) - -u -b 3M -t 30 -R + -u -b 3M -t 20 -R rfsim5g_ue rfsim5g_ext_dn 5 @@ -192,7 +192,7 @@ Iperf Iperf (UL/1Mbps/UDP)(30 sec) - -u -b 1M -t 30 + -u -b 1M -t 20 rfsim5g_ue rfsim5g_ext_dn 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml index 944d9fafc6..e970c7ae3f 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml @@ -87,7 +87,7 @@ Iperf Iperf (DL/3Mbps/UDP)(30 sec) - -u -b 3M -t 30 -R + -u -b 3M -t 20 -R rfsim5g_ue rfsim5g_ext_dn 5 @@ -97,7 +97,7 @@ Iperf Iperf (UL/1Mbps/UDP)(30 sec) - -u -b 1M -t 30 + -u -b 1M -t 20 rfsim5g_ue rfsim5g_ext_dn 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml index 9cc87f830d..8c4aa6e2e4 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml @@ -87,7 +87,7 @@ Iperf Iperf (DL/3Mbps/UDP)(30 sec) - -u -b 3M -t 30 -R + -u -b 3M -t 20 -R rfsim5g_ue rfsim5g_ext_dn 5 @@ -97,7 +97,7 @@ Iperf Iperf (UL/1Mbps/UDP)(30 sec) - -u -b 1M -t 30 + -u -b 1M -t 20 rfsim5g_ue rfsim5g_ext_dn 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml index 3020f63055..7c50eb7fea 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml @@ -88,7 +88,7 @@ Iperf Iperf (DL/30kbps/UDP)(30 sec) - -u -b 0.03M -t 30 -R -c 10.0.1.1 + -u -b 0.03M -t 20 -R -c 10.0.1.1 rfsim5g_ue rfsim5g_gnb_nos1 5 @@ -98,7 +98,7 @@ Iperf Iperf (UL/30kbps/UDP)(30 sec) - -u -b 0.03M -t 30 -c 10.0.1.1 + -u -b 0.03M -t 20 -c 10.0.1.1 rfsim5g_ue rfsim5g_gnb_nos1 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml index 964e1f6ac4..64f19e1314 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml @@ -87,7 +87,7 @@ Iperf Iperf (DL/3Mbps/UDP)(30 sec) - -u -b 3M -t 30 -R + -u -b 3M -t 20 -R rfsim5g_ue rfsim5g_ext_dn 5 @@ -97,7 +97,7 @@ Iperf Iperf (UL/1Mbps/UDP)(30 sec) - -u -b 1M -t 30 + -u -b 1M -t 20 rfsim5g_ue rfsim5g_ext_dn 5 From c49ed17c576dbf7e81edb74854c1ecebefda86e7 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 9 Aug 2024 15:13:02 +0200 Subject: [PATCH 20/23] CI: Modify rfsim5g 2x2 testcase to use 100 MHz bandwidth --- ...nf => gnb.sa.band78.273prb.rfsim.2x2.conf} | 22 ++++++++----------- .../xml_files/container_5g_rfsim_2x2.xml | 8 +++---- .../5g_rfsimulator_2x2/docker-compose.yaml | 4 ++-- 3 files changed, 15 insertions(+), 19 deletions(-) rename ci-scripts/conf_files/{gnb.sa.band78.106prb.rfsim.2x2.conf => gnb.sa.band78.273prb.rfsim.2x2.conf} (96%) diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf similarity index 96% rename from ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf rename to ci-scripts/conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf index 5e77c29ce2..c8f038db9a 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf @@ -32,20 +32,20 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 - absoluteFrequencySSB = 621312; + absoluteFrequencySSB = 630048; dl_frequencyBand = 78; # this is 3300.60 MHz - dl_absoluteFrequencyPointA = 620040; + dl_absoluteFrequencyPointA = 626772; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 dl_subcarrierSpacing = 1; - dl_carrierBandwidth = 106; + dl_carrierBandwidth = 273; #initialDownlinkBWP #genericParameters # this is RBstart=27,L=48 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952 + initialDLBWPlocationAndBandwidth = 1099; # 6366 12925 12956 28875 12952 # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 1; @@ -61,11 +61,11 @@ gNBs = # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 ul_subcarrierSpacing = 1; - ul_carrierBandwidth = 106; + ul_carrierBandwidth = 273; pMax = 20; #initialUplinkBWP #genericParameters - initialULBWPlocationAndBandwidth = 28875; + initialULBWPlocationAndBandwidth = 1099; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialULBWPsubcarrierSpacing = 1; @@ -140,10 +140,10 @@ gNBs = # 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; + dl_UL_TransmissionPeriodicity = 5; + nrofDownlinkSlots = 3; nrofDownlinkSymbols = 6; - nrofUplinkSlots = 2; + nrofUplinkSlots = 1; nrofUplinkSymbols = 4; ssPBCH_BlockPower = -25; @@ -179,9 +179,6 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; - #pusch_TargetSNRx10 = 150; - #pucch_TargetSNRx10 = 200; - dl_max_mcs = 16; # there are retransmissions if more } ); @@ -190,7 +187,6 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; prach_dtx_threshold = 120; - #pucch0_dtx_threshold = 120; } ); diff --git a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml index 8c4aa6e2e4..1cd9314e1b 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml @@ -86,8 +86,8 @@ Iperf - Iperf (DL/3Mbps/UDP)(30 sec) - -u -b 3M -t 20 -R + Iperf (DL/10Mbps/UDP)(30 sec) + -u -b 10M -t 20 -R rfsim5g_ue rfsim5g_ext_dn 5 @@ -96,8 +96,8 @@ Iperf - Iperf (UL/1Mbps/UDP)(30 sec) - -u -b 1M -t 20 + Iperf (UL/4Mbps/UDP)(30 sec) + -u -b 4M -t 20 rfsim5g_ue rfsim5g_ext_dn 5 diff --git a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml index 8cc47c77c6..29600aa655 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml @@ -94,7 +94,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" interval: 10s @@ -110,7 +110,7 @@ services: - NET_ADMIN # for interface bringup - NET_RAW # for ping environment: - USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 --band 78 -C 3319680000 --ue-nb-ant-tx 2 --uicc0.imsi 208990100001100 --ue-nb-ant-rx 2 --uecap_file /opt/oai-nr-ue/etc/uecap.xml --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 273 --numerology 1 --band 78 -C 3450720000 --ssb 1518 --ue-nb-ant-tx 2 --uicc0.imsi 208990100001100 --ue-nb-ant-rx 2 --uecap_file /opt/oai-nr-ue/etc/uecap.xml --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: From 196051655466e4303c597de937171e20fe110cf1 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 9 Aug 2024 15:13:51 +0200 Subject: [PATCH 21/23] CI: Add NTN GEO testcase to RF-Sim 5G --- .../gnb.sa.band66.ntn.25prb.rfsim.conf | 283 ++++++++++++++++++ .../xml_files/container_5g_rfsim_ntn_geo.xml | 91 ++++++ .../container_5g_rfsim_ntn_geo_down.xml | 45 +++ .../docker-compose.yaml | 145 +++++++++ 4 files changed, 564 insertions(+) create mode 100644 ci-scripts/conf_files/gnb.sa.band66.ntn.25prb.rfsim.conf create mode 100644 ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml create mode 100644 ci-scripts/xml_files/container_5g_rfsim_ntn_geo_down.xml create mode 100644 ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml diff --git a/ci-scripts/conf_files/gnb.sa.band66.ntn.25prb.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band66.ntn.25prb.rfsim.conf new file mode 100644 index 0000000000..19874563ae --- /dev/null +++ b/ci-scripts/conf_files/gnb.sa.band66.ntn.25prb.rfsim.conf @@ -0,0 +1,283 @@ +Active_gNBs = ( "5G-GOA-gNB"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "5G-GOA-gNB"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); + nr_cellid = 12345678L; + + ////////// Physical parameters: + + sib1_tda = 5; + min_rxtxtime = 6; + disable_harq = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 2150.43 MHz + 14 PRBs@15kHz SCS (same as initial BWP), points to Subcarrier 0 of RB#10 of SSB block + absoluteFrequencySSB = 430590; + dl_frequencyBand = 66; + # this is 2150.43 MHz + dl_absoluteFrequencyPointA = 430086; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 0; + dl_carrierBandwidth = 25; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=25 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6600; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 0; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 2; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 66; + # this is 1750.43 MHz + ul_absoluteFrequencyPointA = 350086; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 0; + ul_carrierBandwidth = 25; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6600; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 0; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 0; +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0; + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 0; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 0; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + + #ext2 + #ntn_Config_r17 + cellSpecificKoffset_r17 = 478; + } + + ); + + TIMERS : + { + sr_ProhibitTimer = 0; + sr_TransMax = 64; + sr_ProhibitTimer_v1700 = 512; + t300 = 2000; + t301 = 2000; + t319 = 2000; + }; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "192.168.71.132"; }); + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/26"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.140/26"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 150; + pucch_TargetSNRx10 = 200; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 150; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( + { + local_rf = "yes"; + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + sf_extension = 0; + eNB_instances = [0]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "type=x300"; + clock_src = "internal"; + # if_freq = 3700000000L; + # if_offset = 1000000; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_DISABLE"; + } +); + +rfsimulator : +{ + serveraddr = "server"; + serverport = 4043; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="debug"; + f1ap_log_level ="debug"; +}; + diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml new file mode 100644 index 0000000000..3e34d0eeed --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml @@ -0,0 +1,91 @@ + + + rfsim-5gnr-ntn-geo + Monolithic SA NTN GEO gNB + wrench + 1 + + 111111 + 100001 + 000001 + 000002 + 000003 + 020001 + 020002 + 100001 + + + + + Pull_Local_Registry + Pull Images from Local Registry + 0 + oai-gnb-asan oai-nr-ue-asan + + + + DeployGenObject + Deploy OAI 5G CoreNetwork + yaml_files/5g_rfsimulator_ntn_geo + mysql oai-amf oai-smf oai-upf oai-ext-dn + 5 + + + + DeployGenObject + Deploy OAI 5G gNB+nrUE RF sim SA + yaml_files/5g_rfsimulator_ntn_geo + oai-gnb oai-nr-ue + 7 + + + + Attach_UE + Attach OAI UE (Wait for IP) + rfsim5g_ue + + + + Ping + Ping ext-dn from NR-UE + rfsim5g_ue + -c 20 -i 0.25 192.168.72.135 + 5 + + + + Ping + Ping NR-UE from ext-dn + rfsim5g_ext_dn + -c 20 -i 0.25 12.1.1.2 + 5 + + + + UndeployGenObject + Undeploy all OAI 5G stack + yaml_files/5g_rfsimulator_ntn_geo + + + diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo_down.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo_down.xml new file mode 100644 index 0000000000..53fa83806a --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo_down.xml @@ -0,0 +1,45 @@ + + + rfsim-5gnr-ntn-geo-down + CleanUp SA Monolithic NTN GEO gNB + trash + + 100002 + 222222 + + + + + UndeployGenObject + Undeploy all OAI 5G stack + yaml_files/5g_rfsimulator_ntn_geo + + + + Clean_Test_Server_Images + Clean Test Images on Test Server + 0 + + + diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml new file mode 100644 index 0000000000..983969d840 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml @@ -0,0 +1,145 @@ +services: + mysql: + container_name: "rfsim5g-mysql" + image: mysql:8.0 + 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 + retries: 30 + networks: + public_net: + ipv4_address: 192.168.71.131 + oai-amf: + container_name: "rfsim5g-oai-amf" + image: oaisoftwarealliance/oai-amf:v2.0.0 + 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.0.0 + 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.0.0 + 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 + traffic_net: + ipv4_address: 192.168.72.134 + oai-ext-dn: + privileged: true + container_name: rfsim5g-oai-ext-dn + image: oaisoftwarealliance/trf-gen-cn5g:focal + 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 + oai-gnb: + image: oaisoftwarealliance/oai-gnb:develop + container_name: rfsim5g-oai-gnb + cap_drop: + - ALL + environment: + USE_ADDITIONAL_OPTIONS: --sa --rfsim --rfsimulator.prop_delay 238.74 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 + depends_on: + - oai-ext-dn + networks: + public_net: + ipv4_address: 192.168.71.140 + volumes: + - ../../conf_files/gnb.sa.band66.ntn.25prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 + + oai-nr-ue: + image: oaisoftwarealliance/oai-nr-ue: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: --band 66 -C 2152680000 --CO -400000000 -r 25 --numerology 0 --ssb 48 --sa --rfsim --rfsimulator.prop_delay 238.74 --ntn-koffset 478 --ntn-ta-common 477.48 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + depends_on: + - oai-gnb + networks: + public_net: + ipv4_address: 192.168.71.150 + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + +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" From fad450cbe3a63365b9a5a0b0712baeb98bd0df12 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Tue, 13 Aug 2024 12:02:27 +0200 Subject: [PATCH 22/23] Skip UE Log Analysis During Sidelink Testing Bypass UE log analysis when testing sidelink, as it fails due to the absence of expected information and patterns (not present in sidelink communication). Instead, a custom command is used to verify the success of sidelink tests by checking for the presence of "PSBCH RX:OK" in the log of the second UE. --- ci-scripts/cls_oaicitest.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 037f0fdf19..53a9aefda6 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -932,8 +932,11 @@ class OaiCiTest(): global_status = CONST.ALL_PROCESSES_OK for line in ue_log_file.readlines(): result = re.search('nr_synchro_time|Starting NR UE soft modem', str(line)) + sidelink = re.search('sl-mode', str(line)) if result is not None: nrUEFlag = True + if sidelink is not None: + nrUEFlag = False if nrUEFlag: result = re.search('decode mib', str(line)) if result is not None: From 370062c04c1ffb1f5b60356999929e132d63dceb Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 9 Aug 2024 21:52:31 +0200 Subject: [PATCH 23/23] CI: Add sidelink test to RF-Sim 5G --- .../xml_files/container_5g_rfsim_sidelink.xml | 83 +++++++++++++++++++ .../container_5g_rfsim_sidelink_down.xml | 45 ++++++++++ .../docker-compose.yaml | 66 +++++++++++++++ 3 files changed, 194 insertions(+) create mode 100644 ci-scripts/xml_files/container_5g_rfsim_sidelink.xml create mode 100644 ci-scripts/xml_files/container_5g_rfsim_sidelink_down.xml create mode 100644 ci-scripts/yaml_files/5g_rfsimulator_sidelink/docker-compose.yaml diff --git a/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml b/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml new file mode 100644 index 0000000000..3346ace418 --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml @@ -0,0 +1,83 @@ + + + rfsim-5gnr-sidelink + Sidelink test + wrench + 1 + + 111111 + 000002 + 000003 + 000004 + 000005 + 100001 + + + + + Pull_Local_Registry + Pull Images from Local Registry + 0 + oai-nr-ue-asan + + + + DeployGenObject + Deploy OAI 5G UE 1 + yaml_files/5g_rfsimulator_sidelink + oai-nr-ue-1 + 1 + + + + DeployGenObject + Deploy OAI 5G UE 2 + yaml_files/5g_rfsimulator_sidelink + oai-nr-ue-2 + 1 + + + + IdleSleep + Sleep + 20 + + + + Custom_Command + Check that UE synched + localhost + docker logs rfsim5g-oai-nr-ue-2 | grep -m 1 "PSBCH RX:OK" + yes + + + + UndeployGenObject + Undeploy all OAI 5G stack + yaml_files/5g_rfsimulator_sidelink + 1,0,0,0 + 1,0,0,0 + + + diff --git a/ci-scripts/xml_files/container_5g_rfsim_sidelink_down.xml b/ci-scripts/xml_files/container_5g_rfsim_sidelink_down.xml new file mode 100644 index 0000000000..46661e3dc4 --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim_sidelink_down.xml @@ -0,0 +1,45 @@ + + + rfsim-5gnr-sidelink-down + CleanUp sidelink test + trash + + 100002 + 222222 + + + + + UndeployGenObject + Undeploy all OAI 5G stack + yaml_files/5g_rfsimulator_sidelink + + + + Clean_Test_Server_Images + Clean Test Images on Test Server + 0 + + + diff --git a/ci-scripts/yaml_files/5g_rfsimulator_sidelink/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_sidelink/docker-compose.yaml new file mode 100644 index 0000000000..684962b0a6 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator_sidelink/docker-compose.yaml @@ -0,0 +1,66 @@ +services: + oai-nr-ue-1: + image: oaisoftwarealliance/oai-nr-ue:develop + container_name: rfsim5g-oai-nr-ue-1 + cap_drop: + - ALL + cap_add: + - NET_ADMIN + - NET_RAW + environment: + USE_ADDITIONAL_OPTIONS: --sl-mode 2 --sync-ref 4 --rfsim --rfsimulator.serveraddr server --log_config.global_log_options level,nocolor,time + networks: + public_net: + ipv4_address: 192.168.71.140 + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + + oai-nr-ue-2: + image: oaisoftwarealliance/oai-nr-ue:develop + container_name: rfsim5g-oai-nr-ue-2 + cap_drop: + - ALL + cap_add: + - NET_ADMIN # for interface bringup + - NET_RAW # for ping + environment: + USE_ADDITIONAL_OPTIONS: --sl-mode 2 --rfsim --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + depends_on: + - oai-nr-ue-1 + networks: + public_net: + ipv4_address: 192.168.71.150 + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + +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"