diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index f7811cb204..f7ea7304e4 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -376,6 +376,115 @@ int get_nb_periods_per_frame(uint8_t tdd_period) return nb_periods_per_frame; } +void get_delta_arfcn(int i, uint32_t nrarfcn, uint64_t N_OFFs) +{ + uint32_t delta_arfcn = nrarfcn - N_OFFs; + + if(delta_arfcn % (nr_bandtable[i].step_size) != 0) + LOG_E(NR_MAC, "nrarfcn %u is not on the channel raster for step size %lu\n", nrarfcn, nr_bandtable[i].step_size); +} + +uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, uint32_t bw) +{ + uint64_t dl_CarrierFreq_by_1k = dl_CarrierFreq / 1000; + int bw_kHz = bw / 1000; + uint32_t nrarfcn; + int i = get_nr_table_idx(nr_bandP, scs_index); + + LOG_I(NR_MAC,"Searching for nr band %d DL Carrier frequency %llu bw %u\n", nr_bandP, (long long unsigned int)dl_CarrierFreq,bw); + + AssertFatal(dl_CarrierFreq_by_1k >= nr_bandtable[i].dl_min, + "Band %d, bw %u : DL carrier frequency %llu kHz < %llu\n", + nr_bandP, bw, (long long unsigned int)dl_CarrierFreq_by_1k, + (long long unsigned int)nr_bandtable[i].dl_min); + AssertFatal(dl_CarrierFreq_by_1k <= (nr_bandtable[i].dl_max - bw_kHz/2), + "Band %d, dl_CarrierFreq %llu bw %u: DL carrier frequency %llu kHz > %llu\n", + nr_bandP, (long long unsigned int)dl_CarrierFreq,bw, (long long unsigned int)dl_CarrierFreq_by_1k, + (long long unsigned int)(nr_bandtable[i].dl_max - bw_kHz/2)); + + int deltaFglobal = 60; + uint32_t N_REF_Offs = 2016667; + uint64_t F_REF_Offs_khz = 24250080; + + if (dl_CarrierFreq < 24.25e9) { + deltaFglobal = 15; + N_REF_Offs = 600000; + F_REF_Offs_khz = 3000000; + } + if (dl_CarrierFreq < 3e9) { + deltaFglobal = 5; + N_REF_Offs = 0; + F_REF_Offs_khz = 0; + } + + // This is equation before Table 5.4.2.1-1 in 38101-1-f30 + // F_REF=F_REF_Offs + deltaF_Global(N_REF-NREF_REF_Offs) + nrarfcn = (((dl_CarrierFreq_by_1k - F_REF_Offs_khz) / deltaFglobal) + N_REF_Offs); + //get_delta_arfcn(i, nrarfcn, nr_bandtable[i].N_OFFs_DL); + + return nrarfcn; +} + +// This function computes the RF reference frequency from the NR-ARFCN according to 5.4.2.1 of 3GPP TS 38.104 +// this function applies to both DL and UL +uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t nrarfcn) +{ + int deltaFglobal = 5; + uint32_t N_REF_Offs = 0; + uint64_t F_REF_Offs_khz = 0; + uint64_t N_OFFs, frequency, freq_min; + int i = get_nr_table_idx(nr_bandP, scs_index); + + if (nrarfcn > 599999 && nrarfcn < 2016667) { + deltaFglobal = 15; + N_REF_Offs = 600000; + F_REF_Offs_khz = 3000000; + } + if (nrarfcn > 2016666 && nrarfcn < 3279166) { + deltaFglobal = 60; + N_REF_Offs = 2016667; + F_REF_Offs_khz = 24250080; + } + + int32_t delta_duplex = get_delta_duplex(nr_bandP, scs_index); + + if (delta_duplex <= 0){ // DL band >= UL band + if (nrarfcn >= nr_bandtable[i].N_OFFs_DL){ // is TDD of FDD DL + N_OFFs = nr_bandtable[i].N_OFFs_DL; + freq_min = nr_bandtable[i].dl_min; + } else {// is FDD UL + N_OFFs = nr_bandtable[i].N_OFFs_DL + delta_duplex/deltaFglobal; + freq_min = nr_bandtable[i].ul_min; + } + } else { // UL band > DL band + if (nrarfcn >= nr_bandtable[i].N_OFFs_DL + delta_duplex / deltaFglobal){ // is FDD UL + N_OFFs = nr_bandtable[i].N_OFFs_DL + delta_duplex / deltaFglobal; + freq_min = nr_bandtable[i].ul_min; + } else { // is FDD DL + N_OFFs = nr_bandtable[i].N_OFFs_DL; + freq_min = nr_bandtable[i].dl_min; + } + } + + LOG_D(NR_MAC, "Frequency from NR-ARFCN for N_OFFs %lu, duplex spacing %d KHz, deltaFglobal %d KHz\n", + N_OFFs, + delta_duplex, + deltaFglobal); + + AssertFatal(nrarfcn >= N_OFFs,"nrarfcn %u < N_OFFs[%d] %llu\n", nrarfcn, nr_bandtable[i].band, (long long unsigned int)N_OFFs); + get_delta_arfcn(i, nrarfcn, N_OFFs); + + frequency = 1000 * (F_REF_Offs_khz + (nrarfcn - N_REF_Offs) * deltaFglobal); + + LOG_D(NR_MAC, "Computing frequency (nrarfcn %llu => %llu KHz (freq_min %llu KHz, NR band %d N_OFFs %llu))\n", + (unsigned long long)nrarfcn, + (unsigned long long)frequency/1000, + (unsigned long long)freq_min, + nr_bandP, + (unsigned long long)N_OFFs); + + return frequency; +} int get_first_ul_slot(int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofUplinkSymbols) { diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 79e587221b..c76969a8e8 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -168,7 +168,8 @@ static inline int get_num_dmrs(uint16_t dmrs_mask ) { } uint64_t reverse_bits(uint64_t in, int n_bits); - +uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t dl_nrarfcn); +uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, uint32_t bw); int get_first_ul_slot(int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofUplinkSymbols); int cce_to_reg_interleaving(const int R, int k, int n_shift, const int C, int L, const int N_regs); int get_SLIV(uint8_t S, uint8_t L); diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 42090c2e9e..f370927378 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -132,6 +132,7 @@ typedef struct { uint16_t cell_id; uint16_t ssb_start_subcarrier; short rsrp_dBm; + long arfcn; rlm_t radiolink_monitoring; // -1 no monitoring, 0 out_of_sync, 1 in_sync } fapi_nr_ssb_pdu_t; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 9e6a8bf7e5..52fc2569bb 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -153,15 +153,7 @@ int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc, stop_meas(&ue->dlsch_channel_estimation_stats); fapiPbch_t result = {0}; - ret = nr_rx_pbch(ue, - proc, - estimateSz, - dl_ch_estimates, - frame_parms, - temp_ptr->i_ssb, - SISO, - &result, - rxdataF); + ret = nr_rx_pbch(ue, proc, estimateSz, dl_ch_estimates, frame_parms, temp_ptr->i_ssb, &result, rxdataF); if (DUMP_PBCH_CH_ESTIMATES && (ret == 0)) { write_output("pbch_ch_estimates.m", "pbch_ch_estimates", dl_ch_estimates, frame_parms->nb_antennas_rx*estimateSz, 1, 1); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index ed30c95fe0..52c9ec5394 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -361,7 +361,6 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, struct complex16 dl_ch_estimates[][estimateSz], NR_DL_FRAME_PARMS *frame_parms, uint8_t i_ssb, - MIMO_mode_t mimo_mode, fapiPbch_t *result, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) { @@ -414,7 +413,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, symbol_offset, frame_parms); #ifdef DEBUG_PBCH - LOG_I(PHY,"[PHY] PBCH Symbol %d ofdm size %d\n",symbol, frame_parms->ofdm_symbol_size ); + LOG_I(PHY,"[PHY] PBCH Symbol %d ofdm size %d\n",symbol, frame_parms->ofdm_symbol_size); LOG_I(PHY,"[PHY] PBCH starting channel_level\n"); #endif @@ -441,14 +440,6 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, rxdataF_comp, symbol);*/ - /* - if (mimo_mode == ALAMOUTI) { - nr_pbch_alamouti(frame_parms,rxdataF_comp,symbol); - } else if (mimo_mode != SISO) { - LOG_I(PHY,"[PBCH][RX] Unsupported MIMO mode\n"); - return(-1); - } - */ int nb=symbol==2 ? 144 : 360; nr_pbch_quantize(pbch_e_rx+pbch_e_rx_idx, (short *)rxdataF_comp[0], diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index 6888f36434..6e37549349 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -294,7 +294,6 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, struct complex16 dl_ch_estimates[][estimateSz], NR_DL_FRAME_PARMS *frame_parms, uint8_t i_ssb, - MIMO_mode_t mimo_mode, fapiPbch_t *result, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index be2c3b3093..7bb1683507 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -109,6 +109,14 @@ void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind, } } +static uint32_t get_ssb_arfcn(NR_DL_FRAME_PARMS *frame_parms) +{ + uint32_t band_size_hz = frame_parms->N_RB_DL * 12 * frame_parms->subcarrier_spacing; + int ssb_center_sc = frame_parms->ssb_start_subcarrier + 120; // ssb is 20 PRBs -> 240 sub-carriers + uint64_t ssb_freq = frame_parms->dl_CarrierFreq - (band_size_hz / 2) + frame_parms->subcarrier_spacing * ssb_center_sc; + return to_nrarfcn(frame_parms->nr_band, ssb_freq, frame_parms->numerology_index, band_size_hz); +} + void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, uint8_t pdu_type, PHY_VARS_NR_UE *ue, @@ -168,6 +176,7 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, ssb_pdu->cell_id = frame_parms->Nid_cell; ssb_pdu->ssb_start_subcarrier = frame_parms->ssb_start_subcarrier; ssb_pdu->rsrp_dBm = ue->measurements.ssb_rsrp_dBm[frame_parms->ssb_index]; + ssb_pdu->arfcn = get_ssb_arfcn(frame_parms); ssb_pdu->radiolink_monitoring = RLM_in_sync; // TODO to be removed from here ssb_pdu->decoded_pdu = true; } @@ -384,7 +393,6 @@ static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue, dl_ch_estimates, &ue->frame_parms, (ue->frame_parms.ssb_index)&7, - SISO, &result, rxdataF); diff --git a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c index ed72823789..78906f5489 100644 --- a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c +++ b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c @@ -32,7 +32,7 @@ void nr_mac_rrc_sync_ind(const module_id_t module_id, const frame_t frame, const bool in_sync) {} -void nr_mac_rrc_msg3_ind(const module_id_t mod_id, int rnti) {} +void nr_mac_rrc_msg3_ind(const module_id_t mod_id, int rnti, int gnb_id) {} void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success) {} @@ -48,6 +48,8 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const frame_t frame, const int slot, const rnti_t rnti, + const uint32_t cellid, + const long arfcn, const channel_t channel, const uint8_t* pduP, const sdu_size_t pdu_len) { return 0; } diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index bfd23b7ffc..7d738c4ed7 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -797,15 +797,7 @@ int main(int argc, char **argv) } fapiPbch_t result; - ret = nr_rx_pbch(UE, - &proc, - estimateSz, - dl_ch_estimates, - frame_parms, - ssb_index%8, - SISO, - &result, - rxdataF); + ret = nr_rx_pbch(UE, &proc, estimateSz, dl_ch_estimates, frame_parms, ssb_index % 8, &result, rxdataF); if (ret==0) { //UE->rx_ind.rx_indication_body->mib_pdu.ssb_index; //not yet detected automatically diff --git a/openair2/COMMON/mac_messages_types.h b/openair2/COMMON/mac_messages_types.h index 9a6817a41c..effdaacff3 100644 --- a/openair2/COMMON/mac_messages_types.h +++ b/openair2/COMMON/mac_messages_types.h @@ -76,7 +76,8 @@ typedef struct NRRrcMacRaInd_s { } NRRrcMacRaInd; typedef struct NRRrcMacMsg3Ind_s { - uint16_t rnti; + uint16_t rnti; + int gnb_id; } NRRrcMacMsg3Ind; typedef struct RrcMacInSyncInd_s { @@ -118,6 +119,8 @@ typedef struct NRRrcMacBcchDataInd_s { bool is_bch; uint8_t rsrq; uint8_t rsrp; + uint32_t phycellid; + long ssb_arfcn; } NRRrcMacBcchDataInd; typedef struct NRRrcMacSBcchDataInd_s { diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index b2db504796..e9f052f20c 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -2248,118 +2248,6 @@ static const uint16_t table_7_3_1_1_2_32[3][15] = { {0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }; -void get_delta_arfcn(int i, uint32_t nrarfcn, uint64_t N_OFFs) -{ - uint32_t delta_arfcn = nrarfcn - N_OFFs; - - if(delta_arfcn % (nr_bandtable[i].step_size) != 0) - LOG_E(NR_MAC, "nrarfcn %u is not on the channel raster for step size %lu\n", nrarfcn, nr_bandtable[i].step_size); -} - -uint32_t to_nrarfcn(int nr_bandP, - uint64_t dl_CarrierFreq, - uint8_t scs_index, - uint32_t bw) -{ - uint64_t dl_CarrierFreq_by_1k = dl_CarrierFreq / 1000; - int bw_kHz = bw / 1000; - uint32_t nrarfcn; - int i = get_nr_table_idx(nr_bandP, scs_index); - - LOG_I(NR_MAC,"Searching for nr band %d DL Carrier frequency %llu bw %u\n",nr_bandP,(long long unsigned int)dl_CarrierFreq,bw); - - AssertFatal(dl_CarrierFreq_by_1k >= nr_bandtable[i].dl_min, - "Band %d, bw %u : DL carrier frequency %llu kHz < %llu\n", - nr_bandP, bw, (long long unsigned int)dl_CarrierFreq_by_1k, - (long long unsigned int)nr_bandtable[i].dl_min); - AssertFatal(dl_CarrierFreq_by_1k <= (nr_bandtable[i].dl_max - bw_kHz/2), - "Band %d, dl_CarrierFreq %llu bw %u: DL carrier frequency %llu kHz > %llu\n", - nr_bandP, (long long unsigned int)dl_CarrierFreq,bw, (long long unsigned int)dl_CarrierFreq_by_1k, - (long long unsigned int)(nr_bandtable[i].dl_max - bw_kHz/2)); - - int deltaFglobal = 60; - uint32_t N_REF_Offs = 2016667; - uint64_t F_REF_Offs_khz = 24250080; - - if (dl_CarrierFreq < 24.25e9) { - deltaFglobal = 15; - N_REF_Offs = 600000; - F_REF_Offs_khz = 3000000; - } - if (dl_CarrierFreq < 3e9) { - deltaFglobal = 5; - N_REF_Offs = 0; - F_REF_Offs_khz = 0; - } - - // This is equation before Table 5.4.2.1-1 in 38101-1-f30 - // F_REF=F_REF_Offs + deltaF_Global(N_REF-NREF_REF_Offs) - nrarfcn = (((dl_CarrierFreq_by_1k - F_REF_Offs_khz)/deltaFglobal)+N_REF_Offs); - //get_delta_arfcn(i, nrarfcn, nr_bandtable[i].N_OFFs_DL); - - return nrarfcn; -} - -// This function computes the RF reference frequency from the NR-ARFCN according to 5.4.2.1 of 3GPP TS 38.104 -// this function applies to both DL and UL -uint64_t from_nrarfcn(int nr_bandP, - uint8_t scs_index, - uint32_t nrarfcn) -{ - int deltaFglobal = 5; - uint32_t N_REF_Offs = 0; - uint64_t F_REF_Offs_khz = 0; - uint64_t N_OFFs, frequency, freq_min; - int i = get_nr_table_idx(nr_bandP, scs_index); - - if (nrarfcn > 599999 && nrarfcn < 2016667) { - deltaFglobal = 15; - N_REF_Offs = 600000; - F_REF_Offs_khz = 3000000; - } - if (nrarfcn > 2016666 && nrarfcn < 3279166) { - deltaFglobal = 60; - N_REF_Offs = 2016667; - F_REF_Offs_khz = 24250080; - } - - int32_t delta_duplex = get_delta_duplex(nr_bandP, scs_index); - - if (delta_duplex <= 0){ // DL band >= UL band - if (nrarfcn >= nr_bandtable[i].N_OFFs_DL){ // is TDD of FDD DL - N_OFFs = nr_bandtable[i].N_OFFs_DL; - freq_min = nr_bandtable[i].dl_min; - } else {// is FDD UL - N_OFFs = nr_bandtable[i].N_OFFs_DL + delta_duplex/deltaFglobal; - freq_min = nr_bandtable[i].ul_min; - } - } else { // UL band > DL band - if (nrarfcn >= nr_bandtable[i].N_OFFs_DL + delta_duplex/deltaFglobal){ // is FDD UL - N_OFFs = nr_bandtable[i].N_OFFs_DL + delta_duplex/deltaFglobal; - freq_min = nr_bandtable[i].ul_min; - } else { // is FDD DL - N_OFFs = nr_bandtable[i].N_OFFs_DL; - freq_min = nr_bandtable[i].dl_min; - } - } - - LOG_D(NR_MAC, "Frequency from NR-ARFCN for N_OFFs %lu, duplex spacing %d KHz, deltaFglobal %d KHz\n", N_OFFs, delta_duplex, deltaFglobal); - - AssertFatal(nrarfcn >= N_OFFs,"nrarfcn %u < N_OFFs[%d] %llu\n", nrarfcn, nr_bandtable[i].band, (long long unsigned int)N_OFFs); - get_delta_arfcn(i, nrarfcn, N_OFFs); - - frequency = 1000 * (F_REF_Offs_khz + (nrarfcn - N_REF_Offs) * deltaFglobal); - - LOG_D(NR_MAC, "Computing frequency (nrarfcn %llu => %llu KHz (freq_min %llu KHz, NR band %d N_OFFs %llu))\n", - (unsigned long long)nrarfcn, - (unsigned long long)frequency/1000, - (unsigned long long)freq_min, - nr_bandP, - (unsigned long long)N_OFFs); - - return frequency; -} - void nr_get_tbs_dl(nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, int x_overhead, uint8_t numdmrscdmgroupnodata, diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 820cbfceeb..33077c6ce2 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -55,10 +55,6 @@ uint32_t get_Y(const NR_SearchSpace_t *ss, int slot, rnti_t rnti); uint8_t get_BG(uint32_t A, uint16_t R); -uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t dl_nrarfcn); - -uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, uint32_t bw); - int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config, int dci_format, int dmrs_TypeA_Position, diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 26ee87bacf..f2527e1e8c 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -1355,21 +1355,40 @@ static void configure_common_BWP_ul(NR_UE_MAC_INST_t *mac, int bwp_id, NR_BWP_Up } void nr_rrc_mac_config_req_reset(module_id_t module_id, - NR_UE_MAC_reset_cause_t reset_cause) + NR_UE_MAC_reset_cause_t cause) { NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - reset_mac_inst(mac); - reset_ra(&mac->ra); - release_mac_configuration(mac); - nr_ue_init_mac(mac); - // Sending to PHY a request to resync - // with no target cell ID - if (reset_cause != DETACH) { - mac->synch_request.Mod_id = module_id; - mac->synch_request.CC_id = 0; - mac->synch_request.synch_req.target_Nid_cell = -1; - mac->if_module->synch_request(&mac->synch_request); + switch (cause) { + case GO_TO_IDLE: + reset_ra(&mac->ra); + release_mac_configuration(mac, cause); + nr_ue_init_mac(mac); + nr_ue_mac_default_configs(mac); + // new sync but no target cell id -> -1 + nr_ue_send_synch_request(mac, module_id, 0, -1); + break; + case DETACH: + reset_ra(&mac->ra); + reset_mac_inst(mac); + nr_ue_reset_sync_state(mac); + release_mac_configuration(mac, cause); + break; + case T300_EXPIRY: + reset_mac_inst(mac); + reset_ra(&mac->ra); + mac->state = UE_SYNC; // still in sync but need to restart RA + break; + case RE_ESTABLISHMENT: + reset_mac_inst(mac); + nr_ue_mac_default_configs(mac); + nr_ue_reset_sync_state(mac); + release_mac_configuration(mac, cause); + // new sync with old cell ID (re-establishment on the same cell) + nr_ue_send_synch_request(mac, module_id, 0, mac->physCellId); + break; + default: + AssertFatal(false, "Invalid MAC reset cause %d\n", cause); } } diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 86ce0c348a..ec3a0d608f 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -205,7 +205,8 @@ NR_UE_MAC_INST_t *get_mac_inst(module_id_t module_id); void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac); void reset_ra(RA_config_t *ra); -void release_mac_configuration(NR_UE_MAC_INST_t *mac); +void release_mac_configuration(NR_UE_MAC_INST_t *mac, + NR_UE_MAC_reset_cause_t cause); /**\brief called at each slot, slot length based on numerology. now use u=0, scs=15kHz, slot=1ms performs BSR/SR/PHR procedures, random access procedure handler and DLSCH/ULSCH procedures. @@ -450,6 +451,9 @@ void nr_get_prach_resources(NR_UE_MAC_INST_t *mac, void prepare_msg4_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack); void configure_initial_pucch(PUCCH_sched_t *pucch, int res_ind); +void nr_ue_reset_sync_state(NR_UE_MAC_INST_t *mac); +void nr_ue_send_synch_request(NR_UE_MAC_INST_t *mac, module_id_t module_id, int cc_id, int cell_id); + void init_RA(NR_UE_MAC_INST_t *mac, NR_PRACH_RESOURCES_t *prach_resources, NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon, diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index c7e43e50f8..968f948631 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -56,12 +56,11 @@ void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) { LOG_I(NR_MAC, "[UE%d] Initializing MAC\n", mac->ue_id); - mac->first_sync_frame = -1; + nr_ue_reset_sync_state(mac); mac->get_sib1 = false; mac->get_otherSI = false; mac->phy_config_request_sent = false; memset(&mac->phy_config, 0, sizeof(mac->phy_config)); - mac->state = UE_NOT_SYNC; mac->si_window_start = -1; mac->servCellIndex = 0; mac->harq_ACK_SpatialBundlingPUCCH = false; @@ -69,6 +68,9 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) mac->uecap_maxMIMO_PDSCH_layers = 0; mac->uecap_maxMIMO_PUSCH_layers_cb = 0; mac->uecap_maxMIMO_PUSCH_layers_nocb = 0; + mac->p_Max = INT_MIN; + mac->p_Max_alt = INT_MIN; + reset_mac_inst(mac); memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements)); memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment)); @@ -76,35 +78,32 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) memset(&mac->ssb_list[i], 0, sizeof(mac->ssb_list[i])); memset(&mac->prach_assoc_pattern[i], 0, sizeof(mac->prach_assoc_pattern[i])); } - for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) { - mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value - mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value - } } void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac) { // default values as defined in 38.331 sec 9.2.2 - mac->scheduling_info.retxBSR_Timer = NR_BSR_Config__retxBSR_Timer_sf10240; - mac->scheduling_info.periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_infinity; - mac->scheduling_info.SR_COUNTER = 0; - mac->scheduling_info.SR_pending = 0; - mac->scheduling_info.sr_ProhibitTimer = 0; - mac->scheduling_info.sr_ProhibitTimer_Running = 0; - mac->scheduling_info.sr_id = -1; // invalid init value + mac->scheduling_info.retxBSR_Timer = NR_BSR_Config__retxBSR_Timer_sf80; + mac->scheduling_info.periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_sf10; + mac->scheduling_info.periodicPHR_Timer = NR_PHR_Config__phr_PeriodicTimer_sf10; + mac->scheduling_info.prohibitPHR_Timer = NR_PHR_Config__phr_ProhibitTimer_sf10; +} - // set init value 0xFFFF, make sure periodic timer and retx time counters are NOT active, after bsr transmission set the value - // configured by the NW. - mac->scheduling_info.periodicBSR_SF = NR_MAC_UE_BSR_TIMER_NOT_RUNNING; - mac->scheduling_info.retxBSR_SF = NR_MAC_UE_BSR_TIMER_NOT_RUNNING; - mac->BSR_reporting_active = NR_BSR_TRIGGER_NONE; +void nr_ue_send_synch_request(NR_UE_MAC_INST_t *mac, module_id_t module_id, int cc_id, int cell_id) +{ + // Sending to PHY a request to resync + mac->synch_request.Mod_id = module_id; + mac->synch_request.CC_id = cc_id; + mac->synch_request.synch_req.target_Nid_cell = cell_id; + mac->if_module->synch_request(&mac->synch_request); +} - for (int i = 0; i < NR_MAX_NUM_LCID; i++) { - LOG_D(NR_MAC, "Applying default logical channel config for LCGID %d\n", i); - mac->scheduling_info.lc_sched_info[i].LCID_buffer_with_data = false; - mac->scheduling_info.lc_sched_info[i].LCID_buffer_remain = 0; - mac->scheduling_info.lc_sched_info[i].Bj = 0; - } +void nr_ue_reset_sync_state(NR_UE_MAC_INST_t *mac) +{ + // reset synchornization status + mac->first_sync_frame = -1; + mac->state = UE_NOT_SYNC; + mac->ra.ra_state = RA_UE_IDLE; } NR_UE_MAC_INST_t *nr_l2_init_ue(int nb_inst) @@ -144,14 +143,16 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac) { // MAC reset according to 38.321 Section 5.12 - nr_ue_mac_default_configs(nr_mac); - // initialize Bj for each logical channel to zero - for (int i = 0; i < NR_MAX_NUM_LCID; i++) + // TODO reset also other status variables of LC, is this ok? + for (int i = 0; i < NR_MAX_NUM_LCID; i++) { nr_mac->scheduling_info.lc_sched_info[i].Bj = 0; + nr_mac->scheduling_info.lc_sched_info[i].LCID_buffer_with_data = false; + nr_mac->scheduling_info.lc_sched_info[i].LCID_buffer_remain = 0; + } - // stop all running timers - // TODO + // TODO stop all running timers + nr_timer_stop(&nr_mac->ra.contention_resolution_timer); // consider all timeAlignmentTimers as expired and perform the corresponding actions in clause 5.2 // TODO @@ -171,10 +172,16 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac) free_and_zero(nr_mac->ra.Msg3_buffer); // cancel any triggered Scheduling Request procedure - // Done in default config + nr_mac->scheduling_info.SR_COUNTER = 0; + nr_mac->scheduling_info.SR_pending = 0; + nr_mac->scheduling_info.sr_ProhibitTimer = 0; + nr_mac->scheduling_info.sr_ProhibitTimer_Running = 0; + nr_mac->scheduling_info.sr_id = -1; // invalid init value // cancel any triggered Buffer Status Reporting procedure - // Done in default config + nr_mac->scheduling_info.periodicBSR_SF = NR_MAC_UE_BSR_TIMER_NOT_RUNNING; + nr_mac->scheduling_info.retxBSR_SF = NR_MAC_UE_BSR_TIMER_NOT_RUNNING; + nr_mac->BSR_reporting_active = NR_BSR_TRIGGER_NONE; // cancel any triggered Power Headroom Reporting procedure // TODO PHR not implemented yet @@ -194,12 +201,24 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac) // TODO beam failure procedure not implemented } -void release_mac_configuration(NR_UE_MAC_INST_t *mac) +void release_mac_configuration(NR_UE_MAC_INST_t *mac, + NR_UE_MAC_reset_cause_t cause) { - asn1cFreeStruc(asn_DEF_NR_MIB, mac->mib); - asn1cFreeStruc(asn_DEF_NR_SI_SchedulingInfo, mac->si_SchedulingInfo); - asn1cFreeStruc(asn_DEF_NR_TDD_UL_DL_ConfigCommon, mac->tdd_UL_DL_ConfigurationCommon); NR_UE_ServingCell_Info_t *sc = &mac->sc_info; + // if cause is Re-establishment, release spCellConfig only + if (cause == GO_TO_IDLE) { + asn1cFreeStruc(asn_DEF_NR_MIB, mac->mib); + asn1cFreeStruc(asn_DEF_NR_SearchSpace, mac->search_space_zero); + asn1cFreeStruc(asn_DEF_NR_ControlResourceSet, mac->coreset0); + asn1cFreeStruc(asn_DEF_NR_SI_SchedulingInfo, mac->si_SchedulingInfo); + asn1cFreeStruc(asn_DEF_NR_TDD_UL_DL_ConfigCommon, mac->tdd_UL_DL_ConfigurationCommon); + for (int i = 0; i < mac->lc_ordered_list.count; i++) { + nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i]; + asn_sequence_del(&mac->lc_ordered_list, i, 0); + free(lc_info); + } + } + asn1cFreeStruc(asn_DEF_NR_CrossCarrierSchedulingConfig, sc->crossCarrierSchedulingConfig); asn1cFreeStruc(asn_DEF_NR_SRS_CarrierSwitching, sc->carrierSwitching); asn1cFreeStruc(asn_DEF_NR_UplinkConfig, sc->supplementaryUplink); @@ -218,20 +237,35 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac) mac->current_DL_BWP = NULL; mac->current_UL_BWP = NULL; - for (int i = 0; i < mac->dl_BWPs.count; i++) - release_dl_BWP(mac, i); - for (int i = 0; i < mac->ul_BWPs.count; i++) - release_ul_BWP(mac, i); - - asn1cFreeStruc(asn_DEF_NR_SearchSpace, mac->search_space_zero); - asn1cFreeStruc(asn_DEF_NR_ControlResourceSet, mac->coreset0); - - for (int i = 0; i < mac->lc_ordered_list.count; i++) { - nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i]; - asn_sequence_del(&mac->lc_ordered_list, i, 0); - free(lc_info); + // in case of re-establishment we don't need to release initial BWP config common + int first_bwp_rel = 0; // first BWP to release + if (cause == RE_ESTABLISHMENT) { + first_bwp_rel = 1; + // release dedicated BWP0 config + NR_UE_DL_BWP_t *bwp = mac->dl_BWPs.array[0]; + NR_BWP_PDCCH_t *pdcch = &mac->config_BWP_PDCCH[0]; + for (int i = 0; pdcch->list_Coreset.count; i++) + asn_sequence_del(&pdcch->list_Coreset, i, 1); + for (int i = 0; pdcch->list_SS.count; i++) + asn_sequence_del(&pdcch->list_SS, i, 1); + asn1cFreeStruc(asn_DEF_NR_PDSCH_Config, bwp->pdsch_Config); + NR_UE_UL_BWP_t *ubwp = mac->ul_BWPs.array[0]; + asn1cFreeStruc(asn_DEF_NR_PUCCH_Config, ubwp->pucch_Config); + asn1cFreeStruc(asn_DEF_NR_SRS_Config, ubwp->srs_Config); + asn1cFreeStruc(asn_DEF_NR_PUSCH_Config, ubwp->pusch_Config); + mac->current_DL_BWP = bwp; + mac->current_UL_BWP = ubwp; + mac->sc_info.initial_dl_BWPSize = bwp->BWPSize; + mac->sc_info.initial_dl_BWPStart = bwp->BWPStart; + mac->sc_info.initial_ul_BWPSize = ubwp->BWPSize; + mac->sc_info.initial_ul_BWPStart = ubwp->BWPStart; } + for (int i = first_bwp_rel; i < mac->dl_BWPs.count; i++) + release_dl_BWP(mac, i); + for (int i = first_bwp_rel; i < mac->ul_BWPs.count; i++) + release_ul_BWP(mac, i); + memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements)); memset(&mac->csirs_measurements, 0, sizeof(mac->csirs_measurements)); memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment)); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index f81a142cd4..f2db3cfa53 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -264,7 +264,7 @@ int8_t nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, { if(ack_nack) { LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n"); - nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len); + nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len); mac->get_sib1 = false; mac->get_otherSI = false; } @@ -3774,7 +3774,7 @@ int nr_write_ce_ulsch_pdu(uint8_t *mac_ce, // - optimize: mu_pusch, j and table_6_1_2_1_1_2_time_dom_res_alloc_A are already defined in nr_ue_procedures static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id) { - frame_t frame = dl_info->frame; + frame_t frame = dl_info->frame; int slot = dl_info->slot; if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack == 0) { @@ -3976,7 +3976,7 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d if (!ra->cfra) { ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); rnti = ra->t_crnti; - nr_mac_rrc_msg3_ind(mac->ue_id, rnti); + nr_mac_rrc_msg3_ind(mac->ue_id, rnti, dl_info->gNB_index); } fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH); if (!pdu) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 02b4d38453..ec27e92030 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -553,6 +553,9 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, pusch_config_pdu->bwp_start = current_UL_BWP->BWPStart; pusch_config_pdu->bwp_size = current_UL_BWP->BWPSize; + pusch_config_pdu->start_symbol_index = tda_info->startSymbolIndex; + pusch_config_pdu->nr_of_symbols = tda_info->nrOfSymbols; + /* Transform precoding */ pusch_config_pdu->transform_precoding = get_transformPrecoding(current_UL_BWP, dci_format, 0); @@ -637,9 +640,6 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, return -1; } - pusch_config_pdu->start_symbol_index = tda_info->startSymbolIndex; - pusch_config_pdu->nr_of_symbols = tda_info->nrOfSymbols; - /* FREQ_HOPPING_FLAG */ if ((pusch_Config!=NULL) && (pusch_Config->frequencyHopping!=NULL) && (pusch_Config->resourceAllocation != NR_PUSCH_Config__resourceAllocation_resourceAllocationType0)){ pusch_config_pdu->frequency_hopping = dci->frequency_hopping_flag.val; diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index f678b2a0ca..d1bda61f82 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -83,6 +83,24 @@ static void release_rlc_entity_from_lcid(nr_rlc_ue_t *ue, logical_chan_id_t chan } } +logical_chan_id_t nr_rlc_get_lcid_from_rb(int ue_id, bool is_srb, int rb_id) +{ + nr_rlc_manager_lock(nr_rlc_ue_manager); + nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id); + for (logical_chan_id_t id = 1; id <= 32; id++) { + nr_rlc_rb_t *rb = &ue->lcid2rb[id - 1]; + if (is_srb) { + if (rb->type == NR_RLC_SRB && rb->choice.srb_id == rb_id) + return id; + } else { + if (rb->type == NR_RLC_DRB && rb->choice.drb_id == rb_id) + return id; + } + } + LOG_E(RLC, "Couldn't find LCID corresponding to %s %d\n", is_srb ? "SRB" : "DRB", rb_id); + return 0; +} + static nr_rlc_entity_t *get_rlc_entity_from_lcid(nr_rlc_ue_t *ue, logical_chan_id_t channel_id) { if (channel_id == 0) @@ -120,7 +138,7 @@ void nr_rlc_release_entity(int rnti, logical_chan_id_t channel_id) void mac_rlc_data_ind(const module_id_t module_idP, const rnti_t rntiP, const eNB_index_t eNB_index, - const frame_t rameP, + const frame_t frameP, const eNB_flag_t enb_flagP, const MBMS_flag_t MBMS_flagP, const logical_chan_id_t channel_idP, @@ -631,9 +649,10 @@ void nr_rlc_reestablish_entity(int rnti, int lc_id) nr_rlc_manager_lock(nr_rlc_ue_manager); nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti); - if (ue == NULL) + if (ue == NULL) { LOG_E(RLC, "RLC instance for the given UE was not found \n"); - + return; + } nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, lc_id); if (rb != NULL) { @@ -644,7 +663,6 @@ void nr_rlc_reestablish_entity(int rnti, int lc_id) } nr_rlc_manager_unlock(nr_rlc_ue_manager); } - void nr_rlc_reconfigure_entity(int rnti, int lc_id, NR_RLC_Config_t *rlc_Config) { nr_rlc_manager_lock(nr_rlc_ue_manager); @@ -703,6 +721,18 @@ void nr_rlc_reconfigure_entity(int rnti, int lc_id, NR_RLC_Config_t *rlc_Config) AssertFatal(um->ul_UM_RLC.sn_FieldLength == NULL, "Cannot handle different sn_FieldLength for DL and UL\n"); nr_rlc_entity_um_reconfigure(rb, t_reassembly, sn_field_length); } + } else { + AssertFatal(rb->stats.mode == NR_RLC_AM, "Invalid RLC mode\n"); + // default values as in 9.2.1 of 38.331 + int sn_field_length = 12; + nr_rlc_entity_am_reconfigure(rb, + 45, //t_poll_retransmit + 35, //t_reassembly + 0, //t_status_prohibit + -1, //poll_pdu + -1, //poll_byte + 8, //max_retx_threshold + &sn_field_length); } nr_rlc_manager_unlock(nr_rlc_ue_manager); } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h index 4f4578ec80..607538b15c 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h @@ -45,6 +45,7 @@ void nr_rlc_add_srb(int rnti, int srb_id, const NR_RLC_BearerConfig_t *rlc_Beare void nr_rlc_add_drb(int rnti, int drb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig); void nr_rlc_reestablish_entity(int rnti, int lc_id); +logical_chan_id_t nr_rlc_get_lcid_from_rb(int ue_id, bool is_srb, int rb_id); void nr_rlc_remove_ue(int rnti); bool nr_rlc_update_rnti(int from_rnti, int to_rnti); diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 7f9f5aa55e..7557608bd4 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1039,6 +1039,7 @@ static int handle_bcch_bch(NR_UE_MAC_INST_t *mac, uint32_t ssb_index, uint32_t ssb_length, uint16_t ssb_start_subcarrier, + long ssb_arfcn, uint16_t cell_id) { mac->mib_ssb = ssb_index; @@ -1048,7 +1049,8 @@ static int handle_bcch_bch(NR_UE_MAC_INST_t *mac, mac->frequency_range = FR2; else mac->frequency_range = FR1; - nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, NR_BCCH_BCH, (uint8_t *) pduP, 3); // fixed 3 bytes MIB PDU + // fixed 3 bytes MIB PDU + nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, cell_id, ssb_arfcn, NR_BCCH_BCH, (uint8_t *) pduP, 3); return 0; } @@ -1227,6 +1229,7 @@ static uint32_t nr_ue_dl_processing(nr_downlink_indication_t *dl_info) rx_indication_body.ssb_pdu.ssb_index, rx_indication_body.ssb_pdu.ssb_length, rx_indication_body.ssb_pdu.ssb_start_subcarrier, + rx_indication_body.ssb_pdu.arfcn, rx_indication_body.ssb_pdu.cell_id)) << FAPI_NR_RX_PDU_TYPE_SSB; } break; diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 5b50ecb44e..82798b4b75 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -979,7 +979,10 @@ uint8_t do_NR_ULInformationTransfer(uint8_t **buffer, uint32_t pdu_length, uint8 return encoded; } -uint8_t do_RRCReestablishmentRequest(uint8_t *buffer, uint16_t c_rnti) +uint8_t do_RRCReestablishmentRequest(uint8_t *buffer, + NR_ReestablishmentCause_t cause, + uint32_t cell_id, + uint16_t c_rnti) { asn_enc_rval_t enc_rval; NR_UL_CCCH_Message_t ul_ccch_msg; @@ -994,16 +997,16 @@ uint8_t do_RRCReestablishmentRequest(uint8_t *buffer, uint16_t c_rnti) rrcReestablishmentRequest = ul_ccch_msg.message.choice.c1->choice.rrcReestablishmentRequest; // test - rrcReestablishmentRequest->rrcReestablishmentRequest.reestablishmentCause = NR_ReestablishmentCause_reconfigurationFailure; + rrcReestablishmentRequest->rrcReestablishmentRequest.reestablishmentCause = cause; rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.c_RNTI = c_rnti; - rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.physCellId = 0; + rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.physCellId = cell_id; + // TODO properly setting shortMAC-I (see 5.3.7.4 of 331) rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.shortMAC_I.buf = buf; rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.shortMAC_I.buf[0] = 0x08; rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.shortMAC_I.buf[1] = 0x32; rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.shortMAC_I.size = 2; - - if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_NR_UL_CCCH_Message, (void *)&ul_ccch_msg); } diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 143717390c..de57a339d5 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -131,7 +131,10 @@ uint8_t do_NR_ULInformationTransfer(uint8_t **buffer, uint32_t pdu_length, uint8_t *pdu_buffer); -uint8_t do_RRCReestablishmentRequest(uint8_t *buffer, uint16_t c_rnti); +uint8_t do_RRCReestablishmentRequest(uint8_t *buffer, + NR_ReestablishmentCause_t cause, + uint32_t cell_id, + uint16_t c_rnti); int do_RRCReestablishment(rrc_gNB_ue_context_t *const ue_context_pP, uint8_t *const buffer, diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index b3eac63e4c..2958609fda 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -54,6 +54,8 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const frame_t frame, const int slot, const rnti_t rnti, + const uint32_t cellid, + const long arfcn, const channel_t channel, const uint8_t* pduP, const sdu_size_t pdu_len) @@ -84,6 +86,8 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, NR_RRC_MAC_BCCH_DATA_IND (message_p).slot = slot; NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu_size = sdu_size; NR_RRC_MAC_BCCH_DATA_IND (message_p).gnb_index = gNB_index; + NR_RRC_MAC_BCCH_DATA_IND (message_p).phycellid = cellid; + NR_RRC_MAC_BCCH_DATA_IND (message_p).ssb_arfcn = arfcn; NR_RRC_MAC_BCCH_DATA_IND (message_p).is_bch = (channel == NR_BCCH_BCH); itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(module_id), message_p); } @@ -122,10 +126,11 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, return(0); } -void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti) +void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, int gnb_id) { MessageDef *message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_MSG3_IND); NR_RRC_MAC_MSG3_IND (message_p).rnti = rnti; + NR_RRC_MAC_MSG3_IND (message_p).gnb_id = gnb_id; itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(mod_id), message_p); } diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index e6d017b878..50ca63e178 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -139,7 +139,7 @@ static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc, static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, NR_RadioBearerConfig_t *const radioBearerConfig); -static void nr_rrc_ue_generate_rrcReestablishmentComplete(NR_RRCReestablishment_t *rrcReestablishment); +static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc, const NR_RRCReestablishment_t *rrcReestablishment); static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_len); static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, int gNB_index, @@ -152,6 +152,18 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig); +static NR_RB_status_t get_DRB_status(const NR_UE_RRC_INST_t *rrc, NR_DRB_Identity_t drb_id) +{ + AssertFatal(drb_id > 0 && drb_id < 33, "Invalid DRB ID %ld\n", drb_id); + return rrc->status_DRBs[drb_id - 1]; +} + +static void set_DRB_status(NR_UE_RRC_INST_t *rrc, NR_DRB_Identity_t drb_id, NR_RB_status_t status) +{ + AssertFatal(drb_id > 0 && drb_id < 33, "Invalid DRB ID %ld\n", drb_id); + rrc->status_DRBs[drb_id - 1] = status; +} + static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, int gNB_index, NR_RRCReconfiguration_t *rrcReconfiguration) @@ -296,11 +308,10 @@ NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int nb_inst) rrc->ue_id = nr_ue; // fill UE-NR-Capability @ UE-CapabilityRAT-Container here. rrc->selected_plmn_identity = 1; - + rrc->ra_trigger = RA_NOT_RUNNING; rrc->dl_bwp_id = 0; rrc->ul_bwp_id = 0; rrc->as_security_activated = false; - rrc->ra_trigger = RA_NOT_RUNNING; FILE *f = NULL; if (uecap_file) @@ -323,8 +334,8 @@ NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int nb_inst) for (int j = 0; j < NR_NUM_SRB; j++) rrc->Srb[j] = RB_NOT_PRESENT; - for (int j = 0; j < MAX_DRBS_PER_UE; j++) - rrc->status_DRBs[j] = RB_NOT_PRESENT; + for (int j = 1; j <= MAX_DRBS_PER_UE; j++) + set_DRB_status(rrc, j, RB_NOT_PRESENT); // SRB0 activated by default rrc->Srb[0] = RB_ESTABLISHED; for (int j = 0; j < NR_MAX_NUM_LCID; j++) @@ -417,10 +428,14 @@ int check_si_status(NR_UE_RRC_SI_INFO *SI_info) /*brief decode BCCH-BCH (MIB) message*/ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc, const uint8_t gNB_index, + const uint32_t phycellid, + const long ssb_arfcn, uint8_t *const bufferP, const uint8_t buffer_len) { NR_BCCH_BCH_Message_t *bcch_message = NULL; + rrc->phyCellID = phycellid; + rrc->arfcn_ssb = ssb_arfcn; asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_BCCH_BCH_Message, @@ -433,6 +448,28 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc, return; } + // Actions following cell selection while T311 is running + NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants; + if (is_nr_timer_active(timers->T311)) { + nr_timer_stop(&timers->T311); + rrc->ra_trigger = RRC_CONNECTION_REESTABLISHMENT; + + // preparing MSG3 for re-establishment in advance + uint8_t buffer[1024]; + int buf_size = do_RRCReestablishmentRequest(buffer, + rrc->reestablishment_cause, + rrc->phyCellID, + rrc->rnti); // old rnti + + nr_rlc_srb_recv_sdu(rrc->ue_id, 0, buffer, buf_size); + + // apply the default MAC Cell Group configuration + // (done at MAC by calling nr_ue_mac_default_configs) + + // apply the timeAlignmentTimerCommon included in SIB1 + // not used + } + int get_sib = 0; if (get_softmodem_params()->sa && bcch_message->message.choice.mib->cellBarred == NR_MIB__cellBarred_notBarred && @@ -565,16 +602,29 @@ static int nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si) static void nr_rrc_handle_msg3_indication(NR_UE_RRC_INST_t *rrc, rnti_t rnti) { + NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants; switch (rrc->ra_trigger) { case INITIAL_ACCESS_FROM_RRC_IDLE: // After SIB1 is received, prepare RRCConnectionRequest rrc->rnti = rnti; // start timer T300 - NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants; nr_timer_start(&tac->T300); break; case RRC_CONNECTION_REESTABLISHMENT: - AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + rrc->rnti = rnti; + nr_timer_start(&tac->T301); + int srb_id = 1; + // re-establish PDCP for SRB1 + nr_pdcp_reestablishment(rrc->ue_id, srb_id, true); + // re-establish RLC for SRB1 + int lc_id = nr_rlc_get_lcid_from_rb(rrc->ue_id, true, 1); + nr_rlc_reestablish_entity(rrc->ue_id, lc_id); + // apply the specified configuration defined in 9.2.1 for SRB1 + nr_rlc_reconfigure_entity(rrc->ue_id, lc_id, NULL); + // suspend integrity protection and ciphering for SRB1 + nr_pdcp_config_set_security(rrc->ue_id, srb_id, 0, NULL, NULL, NULL); + // resume SRB1 + rrc->Srb[srb_id] = RB_ESTABLISHED; break; case DURING_HANDOVER: AssertFatal(1==0, "ra_trigger not implemented yet!\n"); @@ -725,7 +775,8 @@ static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc, if (rrc->active_RLC_entity[lcid]) { if (rlc_bearer->reestablishRLC) nr_rlc_reestablish_entity(rrc->ue_id, lcid); - nr_rlc_reconfigure_entity(rrc->ue_id, lcid, rlc_bearer->rlc_Config); + if (rlc_bearer->rlc_Config) + nr_rlc_reconfigure_entity(rrc->ue_id, lcid, rlc_bearer->rlc_Config); } else { rrc->active_RLC_entity[lcid] = true; AssertFatal(rlc_bearer->servedRadioBearer, "servedRadioBearer mandatory in case of setup\n"); @@ -751,6 +802,11 @@ void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t if(spCellConfig != NULL) { if (spCellConfig->reconfigurationWithSync != NULL) { NR_ReconfigurationWithSync_t *reconfigurationWithSync = spCellConfig->reconfigurationWithSync; + if (reconfigurationWithSync->spCellConfigCommon && + reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon && + reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon->frequencyInfoDL && + reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB) + rrc->arfcn_ssb = *reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB; // perform Reconfiguration with sync according to 5.3.5.5.2 if (!rrc->as_security_activated && rrc->nrRrcState != RRC_STATE_IDLE_NR) { // perform the actions upon going to RRC_IDLE as specified in 5.3.11 @@ -767,9 +823,9 @@ void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t if (rrc->Srb[i] == RB_SUSPENDED) rrc->Srb[i] = RB_ESTABLISHED; } - for (int i = 0; i < MAX_DRBS_PER_UE; i++) { - if (rrc->status_DRBs[i] == RB_SUSPENDED) - rrc->status_DRBs[i] = RB_ESTABLISHED; + for (int i = 1; i <= MAX_DRBS_PER_UE; i++) { + if (get_DRB_status(rrc, i) == RB_SUSPENDED) + set_DRB_status(rrc, i, RB_ESTABLISHED); } // TODO reset MAC } @@ -848,6 +904,11 @@ static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc, // if the RRCSetup is received in response to an RRCReestablishmentRequest // or RRCResumeRequest or RRCResumeRequest1 // TODO none of the procedures implemented yet + if (rrc->ra_trigger == RRC_CONNECTION_REESTABLISHMENT) { + LOG_E(NR_RRC, "Handling of RRCSetup in response of RRCReestablishment not implemented yet. Going back to IDLE.\n"); + nr_rrc_going_to_IDLE(rrc, OTHER, NULL); + return; + } // perform the cell group configuration procedure in accordance with the received masterCellGroup nr_rrc_ue_process_masterCellGroup(rrc, @@ -1169,8 +1230,10 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, if (LOG_DEBUGFLAG(DEBUG_ASN1)) xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void *)radioBearerConfig); - if (radioBearerConfig->srb3_ToRelease) + if (radioBearerConfig->srb3_ToRelease) { nr_pdcp_release_srb(ue_rrc->ue_id, 3); + ue_rrc->Srb[3] = RB_NOT_PRESENT; + } uint8_t kRRCenc[NR_K_KEY_SIZE] = {0}; uint8_t kRRCint[NR_K_KEY_SIZE] = {0}; @@ -1195,7 +1258,8 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, if (radioBearerConfig->srb_ToAddModList != NULL) { for (int cnt = 0; cnt < radioBearerConfig->srb_ToAddModList->list.count; cnt++) { struct NR_SRB_ToAddMod *srb = radioBearerConfig->srb_ToAddModList->list.array[cnt]; - if (ue_rrc->Srb[srb->srb_Identity] == RB_NOT_PRESENT) + if (ue_rrc->Srb[srb->srb_Identity] == RB_NOT_PRESENT) { + ue_rrc->Srb[srb->srb_Identity] = RB_ESTABLISHED; add_srb(false, ue_rrc->ue_id, radioBearerConfig->srb_ToAddModList->list.array[cnt], @@ -1203,21 +1267,28 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, ue_rrc->integrityProtAlgorithm, kRRCenc, kRRCint); + } else { AssertFatal(srb->discardOnPDCP == NULL, "discardOnPDCP not yet implemented\n"); - AssertFatal(srb->reestablishPDCP == NULL, "reestablishPDCP not yet implemented\n"); + if (srb->reestablishPDCP) { + ue_rrc->Srb[srb->srb_Identity] = RB_ESTABLISHED; + nr_pdcp_reestablishment(ue_rrc->ue_id, srb->srb_Identity, true); + // TODO configure the PDCP entity to apply the integrity protection algorithm + // TODO configure the PDCP entity to apply the ciphering algorithm + } if (srb->pdcp_Config && srb->pdcp_Config->t_Reordering) nr_pdcp_reconfigure_srb(ue_rrc->ue_id, srb->srb_Identity, *srb->pdcp_Config->t_Reordering); } - ue_rrc->Srb[srb->srb_Identity] = RB_ESTABLISHED; } } if (radioBearerConfig->drb_ToReleaseList) { for (int cnt = 0; cnt < radioBearerConfig->drb_ToReleaseList->list.count; cnt++) { NR_DRB_Identity_t *DRB_id = radioBearerConfig->drb_ToReleaseList->list.array[cnt]; - if (DRB_id) + if (DRB_id) { nr_pdcp_release_drb(ue_rrc->ue_id, *DRB_id); + set_DRB_status(ue_rrc, *DRB_id, RB_NOT_PRESENT); + } } } @@ -1229,9 +1300,13 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, for (int cnt = 0; cnt < radioBearerConfig->drb_ToAddModList->list.count; cnt++) { struct NR_DRB_ToAddMod *drb = radioBearerConfig->drb_ToAddModList->list.array[cnt]; int DRB_id = drb->drb_Identity; - /* DRB is already established and configured */ - if (ue_rrc->status_DRBs[DRB_id] == RB_ESTABLISHED) { - AssertFatal(drb->reestablishPDCP == NULL, "reestablishPDCP not yet implemented\n"); + if (get_DRB_status(ue_rrc, DRB_id) != RB_NOT_PRESENT) { + if (drb->reestablishPDCP) { + set_DRB_status(ue_rrc, DRB_id, RB_ESTABLISHED); + nr_pdcp_reestablishment(ue_rrc->ue_id, DRB_id, false); + // TODO configure the PDCP entity to apply the integrity protection algorithm + // TODO configure the PDCP entity to apply the ciphering algorithm + } AssertFatal(drb->recoverPDCP == NULL, "recoverPDCP not yet implemented\n"); /* sdap-Config is included (SA mode) */ NR_SDAP_Config_t *sdap_Config = drb->cnAssociation ? drb->cnAssociation->choice.sdap_Config : NULL; @@ -1242,7 +1317,7 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, if (sdap_Config) nr_reconfigure_sdap_entity(sdap_Config, ue_rrc->ue_id, sdap_Config->pdu_Session, DRB_id); } else { - ue_rrc->status_DRBs[DRB_id] = RB_ESTABLISHED; + set_DRB_status(ue_rrc ,DRB_id, RB_ESTABLISHED); add_drb(false, ue_rrc->ue_id, radioBearerConfig->drb_ToAddModList->list.array[cnt], @@ -1272,6 +1347,56 @@ static void nr_rrc_ue_generate_RRCReconfigurationComplete(NR_UE_RRC_INST_t *rrc, nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL); } +static void nr_rrc_ue_process_rrcReestablishment(NR_UE_RRC_INST_t *rrc, + const int gNB_index, + const NR_RRCReestablishment_t *rrcReestablishment) +{ + // implementign procedues as described in 38.331 section 5.3.7.5 + // stop timer T301 + NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants; + nr_timer_stop(&timers->T301); + // store the nextHopChainingCount value + NR_RRCReestablishment_IEs_t *ies = rrcReestablishment->criticalExtensions.choice.rrcReestablishment; + AssertFatal(ies, "Not expecting RRCReestablishment_IEs to be NULL\n"); + // TODO need to understand how to use nextHopChainingCount + // int nh = rrcReestablishment->criticalExtensions.choice.rrcReestablishment->nextHopChainingCount; + + // update the K gNB key based on the current K gNB key or the NH, using the stored nextHopChainingCount value + nr_derive_key_ng_ran_star(rrc->phyCellID, rrc->arfcn_ssb, rrc->kgnb, rrc->kgnb); + + // derive the K RRCenc and K UPenc keys associated with the previously configured cipheringAlgorithm + // derive the K RRCint and K UPint keys associated with the previously configured integrityProtAlgorithm + uint8_t kRRCenc[16] = {0}; + uint8_t kRRCint[16] = {0}; + uint8_t kUPenc[16] = {0}; + uint8_t kUPint[16] = {0}; + + nr_derive_key(UP_ENC_ALG, rrc->cipheringAlgorithm, rrc->kgnb, kUPenc); + nr_derive_key(UP_INT_ALG, rrc->integrityProtAlgorithm, rrc->kgnb, kUPint); + nr_derive_key(RRC_ENC_ALG, rrc->cipheringAlgorithm, rrc->kgnb, kRRCenc); + nr_derive_key(RRC_INT_ALG, rrc->integrityProtAlgorithm, rrc->kgnb, kRRCint); + + // TODO request lower layers to verify the integrity protection of the RRCReestablishment message + // TODO if the integrity protection check of the RRCReestablishment message fails -> go to IDLE + + // configure lower layers to resume integrity protection for SRB1 + // configure lower layers to resume ciphering for SRB1 + int srb_id = 1; + int security_mode = (rrc->integrityProtAlgorithm << 4) + | rrc->cipheringAlgorithm; + nr_pdcp_config_set_security(rrc->ue_id, srb_id, security_mode, kRRCenc, kRRCint, kUPenc); + + // release the measurement gap configuration indicated by the measGapConfig, if configured + rrcPerNB_t *rrcNB = rrc->perNB + gNB_index; + asn1cFreeStruc(asn_DEF_NR_MeasGapConfig, rrcNB->measGapConfig); + + // resetting the RA trigger state after receiving MSG4 with RRCReestablishment + rrc->ra_trigger = RA_NOT_RUNNING; + + // submit the RRCReestablishmentComplete message to lower layers for transmission + nr_rrc_ue_generate_rrcReestablishmentComplete(rrc, rrcReestablishment); +} + static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, const srb_id_t Srb_id, const uint8_t *const Buffer, @@ -1327,7 +1452,7 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, case NR_DL_DCCH_MessageType__c1_PR_rrcReestablishment: LOG_I(NR_RRC, "Logical Channel DL-DCCH (SRB1), Received RRCReestablishment\n"); - nr_rrc_ue_generate_rrcReestablishmentComplete(c1->choice.rrcReestablishment); + nr_rrc_ue_process_rrcReestablishment(rrc, gNB_indexP, c1->choice.rrcReestablishment); break; case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer: { @@ -1442,7 +1567,7 @@ void *rrc_nrue(void *notUsed) LOG_D(NR_RRC, "[UE %ld] Received %s: gNB %d\n", rrc->ue_id, ITTI_MSG_NAME(msg_p), NR_RRC_MAC_BCCH_DATA_IND(msg_p).gnb_index); NRRrcMacBcchDataInd *bcch = &NR_RRC_MAC_BCCH_DATA_IND(msg_p); if (bcch->is_bch) - nr_rrc_ue_decode_NR_BCCH_BCH_Message(rrc, bcch->gnb_index, bcch->sdu, bcch->sdu_size); + nr_rrc_ue_decode_NR_BCCH_BCH_Message(rrc, bcch->gnb_index, bcch->phycellid, bcch->ssb_arfcn, bcch->sdu, bcch->sdu_size); else nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(rrc, bcch->gnb_index, bcch->sdu, bcch->sdu_size, bcch->rsrq, bcch->rsrp); break; @@ -1589,12 +1714,56 @@ static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECa } } -static void nr_rrc_ue_generate_rrcReestablishmentComplete(NR_RRCReestablishment_t *rrcReestablishment) +void nr_rrc_initiate_rrcReestablishment(NR_UE_RRC_INST_t *rrc, + NR_ReestablishmentCause_t cause, + const int gnb_id) +{ + rrc->reestablishment_cause = cause; + + NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants; + rrcPerNB_t *rrcNB = rrc->perNB + gnb_id; + + // reset timers to SIB1 as part of release of spCellConfig + // it needs to be done before handling timers + set_rlf_sib1_timers_and_constants(timers, rrcNB->SInfo.sib1); + + // stop timer T310, if running + nr_timer_stop(&timers->T310); + // stop timer T304, if running + nr_timer_stop(&timers->T304); + // start timer T311 + nr_timer_start(&timers->T311); + // suspend all RBs, except SRB0 + for (int i = 1; i < 4; i++) { + if (rrc->Srb[i] == RB_ESTABLISHED) { + rrc->Srb[i] = RB_SUSPENDED; + nr_pdcp_suspend_srb(rrc->ue_id, i); + } + } + for (int i = 1; i <= MAX_DRBS_PER_UE; i++) { + if (get_DRB_status(rrc, i) == RB_ESTABLISHED) { + set_DRB_status(rrc, i, RB_SUSPENDED); + nr_pdcp_suspend_drb(rrc->ue_id, i); + } + } + // release the MCG SCell(s), if configured + // no SCell configured in our implementation + + // reset MAC + // release spCellConfig, if configured + // perform cell selection in accordance with the cell selection process + nr_rrc_mac_config_req_reset(rrc->ue_id, RE_ESTABLISHMENT); +} + +static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc, + const NR_RRCReestablishment_t *rrcReestablishment) { uint8_t buffer[RRC_BUFFER_SIZE] = {0}; int size = do_RRCReestablishmentComplete(buffer, RRC_BUFFER_SIZE, rrcReestablishment->rrc_TransactionIdentifier); LOG_I(NR_RRC, "[RAPROC] Logical Channel UL-DCCH (SRB1), Generating RRCReestablishmentComplete (bytes %d)\n", size); + int srb_id = 1; // RRC re-establishment complete on SRB1 + nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL); } void *recv_msgs_from_lte_ue(void *args_p) @@ -1839,9 +2008,9 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, // release all radio resources, including release of the RLC entity, // the MAC configuration and the associated PDCP entity // and SDAP for all established RBs - for (int i = 0; i < MAX_DRBS_PER_UE; i++) { - if (rrc->status_DRBs[i] != RB_NOT_PRESENT) { - rrc->status_DRBs[i] = RB_NOT_PRESENT; + for (int i = 1; i <= MAX_DRBS_PER_UE; i++) { + if (get_DRB_status(rrc, i) != RB_NOT_PRESENT) { + set_DRB_status(rrc, i, RB_NOT_PRESENT); nr_pdcp_release_drb(rrc->ue_id, i); } } diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index 4ce65ef036..df9533ce65 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -56,6 +56,7 @@ #include "NR_UE-NR-Capability.h" #include "NR_SL-PreconfigurationNR-r16.h" #include "NR_MasterInformationBlockSidelink.h" +#include "NR_ReestablishmentCause.h" #include "RRC/NR/nr_rrc_common.h" #include "as_message.h" @@ -85,8 +86,6 @@ typedef enum Rrc_State_NR_e { RRC_STATE_INACTIVE_NR, RRC_STATE_CONNECTED_NR, RRC_STATE_DETACH_NR, - RRC_STATE_FIRST_NR = RRC_STATE_IDLE_NR, - RRC_STATE_LAST_NR = RRC_STATE_CONNECTED_NR, } Rrc_State_NR_t; typedef enum requested_SI_List_e { @@ -187,10 +186,14 @@ typedef struct NR_UE_RRC_INST_s { rrcPerNB_t perNB[NB_CNX_UE]; rnti_t rnti; + uint32_t phyCellID; + long arfcn_ssb; OAI_NR_UECapability_t UECap; NR_UE_Timers_Constants_t timers_and_constants; + RA_trigger_t ra_trigger; + NR_ReestablishmentCause_t reestablishment_cause; plmn_t plmnID; NR_BWP_Id_t dl_bwp_id; diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index 1bb3fda06f..556898c304 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -73,6 +73,8 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const frame_t frame, const int slot, const rnti_t rnti, + const uint32_t cellid, + const long arfcn, const channel_t channel, const uint8_t* pduP, const sdu_size_t pdu_len); @@ -86,7 +88,8 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, NR_RRCRelease_t *RRCRelease); void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success); -void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti); +void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, int gnb_id); +void set_rlf_sib1_timers_and_constants(NR_UE_Timers_Constants_t *tac, NR_SIB1_t *sib1); /**\brief RRC UE task. \param void *args_p Pointer on arguments to start the task. */ diff --git a/openair2/RRC/NR_UE/rrc_timers_and_constants.c b/openair2/RRC/NR_UE/rrc_timers_and_constants.c index 80f7007a2b..10f50dbf9b 100644 --- a/openair2/RRC/NR_UE/rrc_timers_and_constants.c +++ b/openair2/RRC/NR_UE/rrc_timers_and_constants.c @@ -121,10 +121,18 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc) bool t300_expired = nr_timer_tick(&timers->T300); if(t300_expired) { - LOG_W(NR_RRC, "Timer T300 expired\n"); + LOG_W(NR_RRC, "Timer T300 expired! No timely response to RRCSetupRequest\n"); handle_t300_expiry(rrc); } + bool t301_expired = nr_timer_tick(&timers->T301); + // Upon T301 expiry, the UE shall perform the actions upon going to RRC_IDLE + // with release cause 'RRC connection failure' + if(t301_expired) { + LOG_W(NR_RRC, "Timer T301 expired! No timely response to RRCReestabilshmentRequest\n"); + nr_rrc_going_to_IDLE(rrc, RRC_CONNECTION_FAILURE, NULL); + } + bool t304_expired = nr_timer_tick(&timers->T304); if(t304_expired) { LOG_W(NR_RRC, "Timer T304 expired\n"); @@ -146,7 +154,7 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc) bool t311_expired = nr_timer_tick(&timers->T311); if(t311_expired) { - LOG_W(NR_RRC, "Timer T311 expired\n"); + LOG_W(NR_RRC, "Timer T311 expired! No suitable cell found in time after initiation of re-establishment\n"); // Upon T311 expiry, the UE shall perform the actions upon going to RRC_IDLE // with release cause 'RRC connection failure' nr_rrc_going_to_IDLE(rrc, RRC_CONNECTION_FAILURE, NULL);