diff --git a/CMakeLists.txt b/CMakeLists.txt index 691cb4aaa8..4d76434190 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1474,6 +1474,7 @@ set (MAC_SRC set (MAC_NR_SRC ${NR_PHY_INTERFACE_DIR}/NR_IF_Module.c + ${NR_PHY_INTERFACE_DIR}/nr_sched_response.c ${NR_GNB_MAC_DIR}/main.c ${NR_GNB_MAC_DIR}/config.c ${NR_GNB_MAC_DIR}/gNB_scheduler.c @@ -2016,7 +2017,9 @@ add_boolean_option(ENABLE_NRQTSCOPE OFF "Build the Qt-Scope" OFF) if (ENABLE_NRQTSCOPE) find_package(Qt5 REQUIRED COMPONENTS Widgets Charts) message ("Qt5 Widgets and Charts found for nrqtscope") - set(QTSCOPE_SOURCE_NR ${OPENAIR1_DIR}/PHY/TOOLS/nr_phy_qt_scope.cpp) + set(QTSCOPE_SOURCE_NR + ${OPENAIR1_DIR}/PHY/TOOLS/nr_phy_qt_scope.cpp + ${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c) # Creates rules for calling the Meta-Object Compiler (moc) on the given source files qt5_wrap_cpp(QTSCOPE_SOURCE_NR ${OPENAIR1_DIR}/PHY/TOOLS/nr_phy_qt_scope.h) add_library(nrqtscope MODULE ${QTSCOPE_SOURCE_NR}) diff --git a/ci-scripts/datalog_rt_stats.1x1.60.yaml b/ci-scripts/datalog_rt_stats.1x1.60.yaml index bf22c6f432..c65c4614d2 100644 --- a/ci-scripts/datalog_rt_stats.1x1.60.yaml +++ b/ci-scripts/datalog_rt_stats.1x1.60.yaml @@ -14,8 +14,8 @@ Ref : L1 Tx processing : 210.0 DLSCH encoding : 137.0 L1 Rx processing : 345.0 - PUSCH inner-receiver : 184.0 - PUSCH decoding : 276.0 + PUSCH inner-receiver : 210.0 + PUSCH decoding : 210.0 Schedule Response : 48.0 DL & UL scheduling timing : 13.0 UL Indication : 60.0 diff --git a/ci-scripts/datalog_rt_stats.60.2x2.yaml b/ci-scripts/datalog_rt_stats.60.2x2.yaml index b0d861d758..50444cc6b0 100644 --- a/ci-scripts/datalog_rt_stats.60.2x2.yaml +++ b/ci-scripts/datalog_rt_stats.60.2x2.yaml @@ -14,10 +14,10 @@ Ref : L1 Tx processing : 400.0 DLSCH encoding : 177.0 L1 Rx processing : 345.0 - PUSCH inner-receiver : 184.0 - PUSCH decoding : 276.0 + PUSCH inner-receiver : 210.0 + PUSCH decoding : 210.0 Schedule Response : 111.0 - DL & UL scheduling timing : 37.0 + DL & UL scheduling timing : 20.0 UL Indication : 127.0 Threshold : feprx : 1.25 diff --git a/ci-scripts/datalog_rt_stats.default.yaml b/ci-scripts/datalog_rt_stats.default.yaml index 971e72944a..8f7f0f015c 100644 --- a/ci-scripts/datalog_rt_stats.default.yaml +++ b/ci-scripts/datalog_rt_stats.default.yaml @@ -14,11 +14,11 @@ Ref : L1 Tx processing : 170.0 DLSCH encoding : 118.0 L1 Rx processing : 305.0 - PUSCH inner-receiver : 117.0 - PUSCH decoding : 303.0 - Schedule Response : 25.0 + PUSCH inner-receiver : 150.0 + PUSCH decoding : 210.0 + Schedule Response : 20.0 DL & UL scheduling timing : 10.0 - UL Indication : 34.0 + UL Indication : 30.0 Threshold : feprx : 1.25 feptx_prec : 1.25 diff --git a/common/utils/threadPool/thread-pool.c b/common/utils/threadPool/thread-pool.c index b351a667b5..f0f4769faf 100644 --- a/common/utils/threadPool/thread-pool.c +++ b/common/utils/threadPool/thread-pool.c @@ -98,6 +98,8 @@ void *one_thread(void *arg) { myThread->runningOnKey=-1; mutexunlock(tp->incomingFifo.lockF); } + else + delNotifiedFIFO_elt(elt); } while (!myThread->terminate); return NULL; } diff --git a/common/utils/threadPool/thread-pool.h b/common/utils/threadPool/thread-pool.h index 0c544e5b0f..b06671c728 100644 --- a/common/utils/threadPool/thread-pool.h +++ b/common/utils/threadPool/thread-pool.h @@ -279,6 +279,8 @@ static inline void pushTpool(tpool_t *t, notifiedFIFO_elt_t *msg) { if (msg->reponseFifo) pushNotifiedFIFO(msg->reponseFifo, msg); + else + delNotifiedFIFO_elt(msg); } } diff --git a/doc/nr-ue-design.md b/doc/nr-ue-design.md index 32abe6bd80..7ee42335d6 100644 --- a/doc/nr-ue-design.md +++ b/doc/nr-ue-design.md @@ -16,19 +16,20 @@ The UE exits when at any point in operation it gets out of synchronization. When ## Initial Synchronization Block ```mermaid graph TD - A(Start) -->|UE_thread| B["readFrame
--Reads samples worth 2 frames"] - B --> |Tpool thread| C["UE_synch
--PSS & SSS detection
--PBCH decode"] - B --> |UE_thread| D["readFrame
--trash samples to unblock radio"] - C --> |Tpool thread| E[syncInFrame
--shift first sample to start of frame] - D --> |UE_thread| E + start(Start) -->|UE_thread| rxRu["RU read
(Reads two frames)"] + rxRu --> |Tpool thread| sync["SSB detection
(PSS & SSS detection
PBCH decoding
SIB decoding)"] + rxRu --> |UE_thread| rxRuDummy["RU read
(Dummy read till sync detection to avoid buffer overflow at radio)"] + sync --> |Tpool thread| frameSync["Frame synchronization
(Shift received samples to align with frame)"] + rxRuDummy --> |UE_thread| frameSync ``` ## Regular Slot Processing ```mermaid graph TD - E[syncInFrame
--shift first sample to start of frame] -->|UE_thread| F["trx_read_func (slot n)"] - F --> |Tpool thread| G["processSlotTX (slot n+4)
--PUSCH encode
--PUCCH encode
--trx_write_func"] - F --> |UE_thread| H["UE_processing (slot n)
--PDCCH decode
--PDSCH decode"] - G --> |Tpool thread| I(Merge) - H --> |UE_thread| I(Merge) - I --> |Go to next slot
UE_thread| F + sync["Frame synchronization
(Shift received samples to align with frame)"] -->|UE_thread| hw_read["RU read (slot n)"] + hw_read --> |UE_thread| rxPreProc["PBCH & PDCCH decoding (slot n)"] + hw_read --> |Tpool thread| txProc["Tx processing (slot n+3)
PUSCH encode
PUCCH encode (wait for DLSCH in slot n+3-k1 to finish)
RU write"] + rxPreProc --> |Tpool thread| rxProc["PDSCH decoding (slot n)"] + rxPreProc --> |UE_thread| join(Merge) + txProc --> |Tpool thread| join + join --> |Go to next slot
UE_thread| hw_read ``` diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 05516e01b4..773f89416c 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -51,6 +51,7 @@ #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/MODULATION/nr_modulation.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" +#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h" #undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all @@ -126,6 +127,8 @@ void tx_func(void *param) { 1); clock_gettime(CLOCK_MONOTONIC,&info->gNB->rt_L1_profiling.return_L1_TX[rt_prof_idx]); + /* this thread is done with the sched_info, decrease the reference counter */ + deref_sched_response(info->sched_response_id); } void rx_func(void *param) diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 6c527defca..6a2b6e7e9f 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -328,7 +328,9 @@ void fh_if5_south_in(RU_t *ru, if (proc->first_rx == 0) { if (proc->tti_rx != *tti) { LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",proc->tti_rx,*tti); - exit_fun("Exiting"); + if (!oai_exit) + exit_fun("Exiting"); + return; } if (proc->frame_rx != *frame) { diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 10509a2870..4024075651 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -203,6 +203,7 @@ static void process_queued_nr_nfapi_msgs(NR_UE_MAC_INST_t *mac, int sfn_slot) nfapi_nr_ul_tti_request_t *ul_tti_request_crc = unqueue_matching(&nr_ul_tti_req_queue, MAX_QUEUE_SIZE, sfn_slot_matcher, &mac->nr_ue_emul_l1.harq[i].active_ul_harq_sfn_slot); if (ul_tti_request_crc && ul_tti_request_crc->n_pdus > 0) { check_and_process_dci(NULL, NULL, NULL, ul_tti_request_crc); + free_and_zero(ul_tti_request_crc); } } @@ -232,6 +233,8 @@ static void process_queued_nr_nfapi_msgs(NR_UE_MAC_INST_t *mac, int sfn_slot) if (get_softmodem_params()->nsa) save_nr_measurement_info(dl_tti_request); check_and_process_dci(dl_tti_request, tx_data_request, NULL, NULL); + free_and_zero(dl_tti_request); + free_and_zero(tx_data_request); } else { AssertFatal(false, "We dont have PDUs in either dl_tti %d or tx_req %d\n", @@ -240,6 +243,7 @@ static void process_queued_nr_nfapi_msgs(NR_UE_MAC_INST_t *mac, int sfn_slot) } if (ul_dci_request && ul_dci_request->numPdus > 0) { check_and_process_dci(NULL, NULL, ul_dci_request, NULL); + free_and_zero(ul_dci_request); } } @@ -324,14 +328,6 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg) if (pthread_mutex_lock(&mac->mutex_dl_info)) abort(); - memset(&mac->dl_info, 0, sizeof(mac->dl_info)); - mac->dl_info.cc_id = CC_id; - mac->dl_info.gNB_index = gNB_id; - mac->dl_info.module_id = mod_id; - mac->dl_info.frame = frame; - mac->dl_info.slot = slot; - mac->dl_info.dci_ind = NULL; - mac->dl_info.rx_ind = NULL; if (ch_info) { mac->nr_ue_emul_l1.pmi = ch_info->csi[0].pmi; mac->nr_ue_emul_l1.ri = ch_info->csi[0].ri; @@ -343,6 +339,14 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg) mac->scc->tdd_UL_DL_ConfigurationCommon : mac->scc_SIB->tdd_UL_DL_ConfigurationCommon, ul_info.slot_rx)) { + memset(&mac->dl_info, 0, sizeof(mac->dl_info)); + mac->dl_info.cc_id = CC_id; + mac->dl_info.gNB_index = gNB_id; + mac->dl_info.module_id = mod_id; + mac->dl_info.frame = frame; + mac->dl_info.slot = slot; + mac->dl_info.dci_ind = NULL; + mac->dl_info.rx_ind = NULL; nr_ue_dl_indication(&mac->dl_info, &ul_time_alignment); } @@ -446,7 +450,7 @@ static void UE_synch(void *arg) { break; */ case pbch: - LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode); + LOG_I(PHY, "[UE thread Synch] Running Initial Synch \n"); uint64_t dl_carrier, ul_carrier; nr_get_carrier_frequencies(UE, &dl_carrier, &ul_carrier); @@ -563,6 +567,12 @@ void processSlotTX(void *arg) { LOG_D(PHY,"%d.%d => slot type %d\n", proc->frame_tx, proc->nr_slot_tx, proc->tx_slot_type); if (proc->tx_slot_type == NR_UPLINK_SLOT || proc->tx_slot_type == NR_MIXED_SLOT){ + // wait for rx slots to send indication (if any) that DLSCH decoding is finished + for(int i=0; i < rxtxD->tx_wait_for_dlsch; i++) { + notifiedFIFO_elt_t *res = pullNotifiedFIFO(UE->tx_resume_ind_fifo[proc->nr_slot_tx]); + delNotifiedFIFO_elt(res); + } + // trigger L2 to run ue_scheduler thru IF module // [TODO] mapping right after NR initial sync if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) { @@ -589,10 +599,8 @@ void processSlotTX(void *arg) { RU_write(rxtxD); } -void UE_processing(nr_rxtx_thread_data_t *rxtxD) { +nr_phy_data_t UE_dl_preprocessing(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { - UE_nr_rxtx_proc_t *proc = &rxtxD->proc; - PHY_VARS_NR_UE *UE = rxtxD->UE; nr_phy_data_t phy_data = {0}; if (IS_SOFTMODEM_NOS1 || get_softmodem_params()->sa) { @@ -624,17 +632,28 @@ void UE_processing(nr_rxtx_thread_data_t *rxtxD) { UE->if_inst->dl_indication(&dl_indication, NULL); } - // Process Rx data for one sub-frame -#ifdef UE_SLOT_PARALLELISATION - phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, no_relay, NULL ); -#else uint64_t a=rdtsc_oai(); - phy_procedures_nrUE_RX(UE, proc, &phy_data); + pbch_pdcch_processing(UE, proc, &phy_data); + if (phy_data.dlsch[0].active) { + // indicate to tx thread to wait for DLSCH decoding + const int ack_nack_slot = (proc->nr_slot_rx + phy_data.dlsch[0].dlsch_config.k1_feedback) % UE->frame_parms.slots_per_frame; + UE->tx_wait_for_dlsch[ack_nack_slot]++; + } + LOG_D(PHY, "In %s: slot %d, time %llu\n", __FUNCTION__, proc->nr_slot_rx, (rdtsc_oai()-a)/3500); -#endif } ue_ta_procedures(UE, proc->nr_slot_tx, proc->frame_tx); + return phy_data; +} + +void UE_dl_processing(void *arg) { + nr_rxtx_thread_data_t *rxtxD = (nr_rxtx_thread_data_t *) arg; + UE_nr_rxtx_proc_t *proc = &rxtxD->proc; + PHY_VARS_NR_UE *UE = rxtxD->UE; + nr_phy_data_t *phy_data = &rxtxD->phy_data; + + pdsch_processing(UE, proc, phy_data); } void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockSize) { @@ -688,7 +707,7 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { - LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode); + LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset); if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) { // Resynchonize by slot (will work with numerology 1 only) @@ -755,7 +774,6 @@ void *UE_thread(void *arg) { fapi_nr_config_request_t *cfg = &UE->nrUE_config; AssertFatal(0== openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), ""); UE->rfdevice.host_type = RAU_HOST; - UE->lost_sync = 0; UE->is_synchronized = 0; AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n"); @@ -774,12 +792,16 @@ void *UE_thread(void *arg) { bool syncRunning=false; const int nb_slot_frame = UE->frame_parms.slots_per_frame; int absolute_slot=0, decoded_frame_rx=INT_MAX, trashed_frames=0; + initNotifiedFIFO(&UE->phy_config_ind); + + int num_ind_fifo = nb_slot_frame; + for(int i=0; i < num_ind_fifo; i++) { + UE->tx_wait_for_dlsch[num_ind_fifo] = 0; + UE->tx_resume_ind_fifo[i] = malloc(sizeof(*UE->tx_resume_ind_fifo[i])); + initNotifiedFIFO(UE->tx_resume_ind_fifo[i]); + } while (!oai_exit) { - if (UE->lost_sync) { - UE->is_synchronized = 0; - UE->lost_sync = 0; - } if (syncRunning) { notifiedFIFO_elt_t *res=tryPullTpool(&nf,&(get_nrUE_params()->Tpool)); @@ -796,6 +818,11 @@ void *UE_thread(void *arg) { decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx); // shift the frame index with all the frames we trashed meanwhile we perform the synch search decoded_frame_rx=(decoded_frame_rx + UE->init_sync_frame + trashed_frames) % MAX_FRAME_NUMBER; + // wait for RRC to configure PHY parameters from SIB + if (get_softmodem_params()->sa) { + notifiedFIFO_elt_t *phy_config_res = pullNotifiedFIFO(&UE->phy_config_ind); + delNotifiedFIFO_elt(phy_config_res); + } } delNotifiedFIFO_elt(res); start_rx_stream=0; @@ -933,15 +960,22 @@ void *UE_thread(void *arg) { curMsgTx->writeBlockSize = writeBlockSize; curMsgTx->proc.timestamp_tx = writeTimestamp; curMsgTx->UE = UE; + curMsgTx->tx_wait_for_dlsch = UE->tx_wait_for_dlsch[curMsgTx->proc.nr_slot_tx]; + UE->tx_wait_for_dlsch[curMsgTx->proc.nr_slot_tx] = 0; pushTpool(&(get_nrUE_params()->Tpool), newElt); - // RX slot processing - UE_processing(&curMsg); + // RX slot processing. We launch and forget. + newElt = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_rx, NULL, UE_dl_processing); + nr_rxtx_thread_data_t *curMsgRx = (nr_rxtx_thread_data_t *) NotifiedFifoData(newElt); + curMsgRx->proc = curMsg.proc; + curMsgRx->UE = UE; + curMsgRx->phy_data = UE_dl_preprocessing(UE, &curMsg.proc); + pushTpool(&(get_nrUE_params()->Tpool), newElt); if (curMsg.proc.decoded_frame_rx != -1) decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | curMsg.proc.decoded_frame_rx); else - decoded_frame_rx=-1; + decoded_frame_rx=-1; if (decoded_frame_rx>0 && decoded_frame_rx != curMsg.proc.frame_rx) LOG_E(PHY,"Decoded frame index (%d) is not compatible with current context (%d), UE should go back to synch mode\n", diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 3c884ea390..8bf0f6efec 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -264,7 +264,6 @@ static void get_options(void) { paramdef_t cmdline_params[] =CMDLINE_NRUEPARAMS_DESC ; int numparams = sizeof(cmdline_params)/sizeof(paramdef_t); config_get(cmdline_params,numparams,NULL); - config_process_cmdline( cmdline_params,numparams,NULL); if (vcdflag > 0) ouput_vcd = 1; @@ -272,38 +271,7 @@ static void get_options(void) { // set PHY vars from command line void set_options(int CC_id, PHY_VARS_NR_UE *UE){ - NR_DL_FRAME_PARMS *fp = &UE->frame_parms; - paramdef_t cmdline_params[] = CMDLINE_NRUE_PHYPARAMS_DESC ; - int numparams = sizeof(cmdline_params)/sizeof(paramdef_t); - - UE->mode = normal_txrx; - - config_get(cmdline_params,numparams,NULL); - - int pindex = config_paramidx_fromname(cmdline_params,numparams, CALIBRX_OPT); - if ( (cmdline_params[pindex].paramflags & PARAMFLAG_PARAMSET) != 0) UE->mode = rx_calib_ue; - - pindex = config_paramidx_fromname(cmdline_params,numparams, CALIBRXMED_OPT); - if ( (cmdline_params[pindex].paramflags & PARAMFLAG_PARAMSET) != 0) UE->mode = rx_calib_ue_med; - - pindex = config_paramidx_fromname(cmdline_params,numparams, CALIBRXBYP_OPT); - if ( (cmdline_params[pindex].paramflags & PARAMFLAG_PARAMSET) != 0) UE->mode = rx_calib_ue_byp; - - pindex = config_paramidx_fromname(cmdline_params,numparams, DBGPRACH_OPT); - if (cmdline_params[pindex].uptr) - if ( *(cmdline_params[pindex].uptr) > 0) UE->mode = debug_prach; - - pindex = config_paramidx_fromname(cmdline_params,numparams,NOL2CONNECT_OPT ); - if (cmdline_params[pindex].uptr) - if ( *(cmdline_params[pindex].uptr) > 0) UE->mode = no_L2_connect; - - pindex = config_paramidx_fromname(cmdline_params,numparams,CALIBPRACH_OPT ); - if (cmdline_params[pindex].uptr) - if ( *(cmdline_params[pindex].uptr) > 0) UE->mode = calib_prach_tx; - - pindex = config_paramidx_fromname(cmdline_params,numparams,DUMPFRAME_OPT ); - if ((cmdline_params[pindex].paramflags & PARAMFLAG_PARAMSET) != 0) - UE->mode = rx_dump_frame; + NR_DL_FRAME_PARMS *fp = &UE->frame_parms; // Init power variables tx_max_power[CC_id] = tx_max_power[0]; @@ -316,9 +284,18 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ UE->tx_power_max_dBm = tx_max_power[CC_id]; UE->rf_map.card = card_offset; UE->rf_map.chain = CC_id + chain_offset; + UE->max_ldpc_iterations = nrUE_params.max_ldpc_iterations; + UE->UE_scan_carrier = nrUE_params.UE_scan_carrier; + UE->UE_fo_compensation = nrUE_params.UE_fo_compensation; + UE->if_freq = nrUE_params.if_freq; + UE->if_freq_off = nrUE_params.if_freq_off; + UE->chest_freq = nrUE_params.chest_freq; + UE->chest_time = nrUE_params.chest_time; + UE->no_timing_correction = nrUE_params.no_timing_correction; + UE->timing_advance = nrUE_params.timing_advance; - LOG_I(PHY,"Set UE mode %d, UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, chest-freq %d\n", - UE->mode, UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->chest_freq); + LOG_I(PHY,"Set UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, chest-freq %d, chest-time %d\n", + UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->chest_freq, UE->chest_time); // Set FP variables @@ -327,10 +304,14 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ LOG_I(PHY, "Set UE frame_type %d\n", fp->frame_type); } - LOG_I(PHY, "Set UE nb_rx_antenna %d, nb_tx_antenna %d, threequarter_fs %d, ssb_start_subcarrier %d\n", fp->nb_antennas_rx, fp->nb_antennas_tx, fp->threequarter_fs, fp->ssb_start_subcarrier); + fp->nb_antennas_rx = nrUE_params.nb_antennas_rx; + fp->nb_antennas_tx = nrUE_params.nb_antennas_tx; + fp->threequarter_fs = nrUE_params.threequarter_fs; + fp->N_RB_DL = nrUE_params.N_RB_DL; + fp->ssb_start_subcarrier = nrUE_params.ssb_start_subcarrier; + fp->ofdm_offset_divisor = nrUE_params.ofdm_offset_divisor; - fp->ofdm_offset_divisor = nrUE_params.ofdm_offset_divisor; - UE->max_ldpc_iterations = nrUE_params.max_ldpc_iterations; + LOG_I(PHY, "Set UE nb_rx_antenna %d, nb_tx_antenna %d, threequarter_fs %d, ssb_start_subcarrier %d\n", fp->nb_antennas_rx, fp->nb_antennas_tx, fp->threequarter_fs, fp->ssb_start_subcarrier); } diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 60b9d91f72..99c97eae28 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -36,54 +36,51 @@ {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, .iptr=&single_thread_flag, .defintval=1, TYPE_INT, 0}, \ {"dlsch-parallel", CONFIG_HLP_DLSCH_PARA, 0, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \ {"offset-divisor", CONFIG_HLP_OFFSET_DIV, 0, .uptr=&nrUE_params.ofdm_offset_divisor, .defuintval=8, TYPE_UINT32, 0}, \ - {"max-ldpc-iterations", CONFIG_HLP_MAX_LDPC_ITERATIONS, 0, .u8ptr=&nrUE_params.max_ldpc_iterations, .defuintval=5, TYPE_UINT8, 0}, \ + {"max-ldpc-iterations", CONFIG_HLP_MAX_LDPC_ITERATIONS, 0, .iptr=&nrUE_params.max_ldpc_iterations, .defuintval=5, TYPE_UINT8, 0}, \ {"nr-dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, .iptr=(int32_t *)&nr_dlsch_demod_shift, .defintval=0, TYPE_INT, 0}, \ {"V" , CONFIG_HLP_VCD, PARAMFLAG_BOOL, .iptr=&vcdflag, .defintval=0, TYPE_INT, 0}, \ {"uecap_file", CONFIG_HLP_UECAP_FILE, 0, .strptr=&uecap_file, .defstrval="./uecap_ports1.xml", TYPE_STRING, 0}, \ {"rrc_config_path", CONFIG_HLP_RRC_CFG_PATH, 0, .strptr=&rrc_config_path, .defstrval="./", TYPE_STRING, 0}, \ - {"ue-idx-standalone", NULL, 0, .u16ptr=&ue_idx_standalone, .defuintval=0xFFFF, TYPE_UINT16, 0} \ -} -// clang-format on - -/*------------------------------------------------------------------------------------------------------------------------------------------*/ -/* command line parameters defining UE running mode */ -/* optname helpstr paramflags XXXptr defXXXval type numelt */ -/*------------------------------------------------------------------------------------------------------------------------------------------*/ -// clang-format off -#define CMDLINE_NRUE_PHYPARAMS_DESC { \ - { CALIBRX_OPT, CONFIG_HLP_CALUER, 0, .iptr=&rx_input_level_dBm, .defintval=0, TYPE_INT, 0}, \ - { CALIBRXMED_OPT, CONFIG_HLP_CALUERM, 0, .iptr=&rx_input_level_dBm, .defintval=0, TYPE_INT, 0}, \ - { CALIBRXBYP_OPT, CONFIG_HLP_CALUERB, 0, .iptr=&rx_input_level_dBm, .defintval=0, TYPE_INT, 0}, \ - { DBGPRACH_OPT, CONFIG_HLP_DBGUEPR, PARAMFLAG_BOOL, .uptr=NULL, .defuintval=1, TYPE_INT, 0}, \ - { NOL2CONNECT_OPT, CONFIG_HLP_NOL2CN, PARAMFLAG_BOOL, .uptr=NULL, .defuintval=1, TYPE_INT, 0}, \ - { CALIBPRACH_OPT, CONFIG_HLP_CALPRACH, PARAMFLAG_BOOL, .uptr=NULL, .defuintval=1, TYPE_INT, 0}, \ - { DUMPFRAME_OPT, CONFIG_HLP_DUMPFRAME, PARAMFLAG_BOOL, .iptr=&dumpframe, .defintval=0, TYPE_INT, 0}, \ + {"ue-idx-standalone", NULL, 0, .u16ptr=&ue_idx_standalone, .defuintval=0xFFFF, TYPE_UINT16, 0}, \ {"ue-rxgain", CONFIG_HLP_UERXG, 0, .dblptr=&(rx_gain[0][0]), .defdblval=110, TYPE_DOUBLE, 0}, \ {"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, .dblptr=&rx_gain_off, .defdblval=0, TYPE_DOUBLE, 0}, \ {"ue-txgain", CONFIG_HLP_UETXG, 0, .dblptr=&(tx_gain[0][0]), .defdblval=0, TYPE_DOUBLE, 0}, \ - {"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, .u8ptr=&(fp->nb_antennas_rx), .defuintval=1, TYPE_UINT8, 0}, \ - {"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, .u8ptr=&(fp->nb_antennas_tx), .defuintval=1, TYPE_UINT8, 0}, \ - {"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, .iptr=&(UE->UE_scan_carrier), .defintval=0, TYPE_INT, 0}, \ - {"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, .iptr=&(UE->UE_fo_compensation), .defintval=0, TYPE_INT, 0}, \ + {"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, .iptr=&(nrUE_params.nb_antennas_rx), .defuintval=1, TYPE_UINT8, 0}, \ + {"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, .iptr=&(nrUE_params.nb_antennas_tx), .defuintval=1, TYPE_UINT8, 0}, \ + {"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, .iptr=&(nrUE_params.UE_scan_carrier), .defintval=0, TYPE_INT, 0}, \ + {"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, .iptr=&(nrUE_params.UE_fo_compensation), .defintval=0, TYPE_INT, 0}, \ {"ue-max-power", NULL, 0, .iptr=&(tx_max_power[0]), .defintval=90, TYPE_INT, 0}, \ - {"A" , CONFIG_HLP_TADV, 0, .iptr=&(UE->timing_advance), .defintval=0, TYPE_INT, 0}, \ - {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, .u8ptr=&(fp->threequarter_fs), .defintval=0, TYPE_UINT8, 0}, \ - {"r" , CONFIG_HLP_PRB_SA, 0, .iptr=&(fp->N_RB_DL), .defintval=106, TYPE_UINT, 0}, \ - {"ssb", CONFIG_HLP_SSC, 0, .u16ptr=&(fp->ssb_start_subcarrier), .defintval=516, TYPE_UINT16, 0}, \ + {"A" , CONFIG_HLP_TADV, 0, .iptr=&(nrUE_params.timing_advance), .defintval=0, TYPE_INT, 0}, \ + {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, .iptr=&(nrUE_params.threequarter_fs), .defintval=0, TYPE_UINT8, 0}, \ + {"r" , CONFIG_HLP_PRB_SA, 0, .iptr=&(nrUE_params.N_RB_DL), .defintval=106, TYPE_UINT, 0}, \ + {"ssb", CONFIG_HLP_SSC, 0, .iptr=&(nrUE_params.ssb_start_subcarrier), .defintval=516, TYPE_UINT16, 0}, \ {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, .iptr=&tddflag, .defintval=0, TYPE_INT, 0}, \ - {"if_freq" , CONFIG_HLP_IF_FREQ, 0, .u64ptr=&(UE->if_freq), .defuintval=0, TYPE_UINT64, 0}, \ - {"if_freq_off" , CONFIG_HLP_IF_FREQ_OFF, 0, .iptr=&(UE->if_freq_off), .defuintval=0, TYPE_INT, 0}, \ - {"chest-freq", CONFIG_HLP_CHESTFREQ, 0, .iptr=&(UE->chest_freq), .defintval=0, TYPE_INT, 0}, \ - {"chest-time", CONFIG_HLP_CHESTTIME, 0, .iptr=&(UE->chest_time), .defintval=0, TYPE_INT, 0}, \ - {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, .iptr=&(UE->no_timing_correction), .defintval=0, TYPE_INT, 0}, \ + {"if_freq" , CONFIG_HLP_IF_FREQ, 0, .u64ptr=&(nrUE_params.if_freq), .defuintval=0, TYPE_UINT64, 0}, \ + {"if_freq_off" , CONFIG_HLP_IF_FREQ_OFF, 0, .iptr=&(nrUE_params.if_freq_off), .defuintval=0, TYPE_INT, 0}, \ + {"chest-freq", CONFIG_HLP_CHESTFREQ, 0, .iptr=&(nrUE_params.chest_freq), .defintval=0, TYPE_INT, 0}, \ + {"chest-time", CONFIG_HLP_CHESTTIME, 0, .iptr=&(nrUE_params.chest_time), .defintval=0, TYPE_INT, 0}, \ + {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, .iptr=&(nrUE_params.no_timing_correction), .defintval=0, TYPE_INT, 0}, \ } // clang-format on typedef struct { uint64_t optmask; //mask to store boolean config options uint32_t ofdm_offset_divisor; // Divisor for sample offset computation for each OFDM symbol - uint8_t max_ldpc_iterations; // number of maximum LDPC iterations + int max_ldpc_iterations; // number of maximum LDPC iterations tpool_t Tpool; // thread pool + int UE_scan_carrier; + int UE_fo_compensation; + int timing_advance; + uint64_t if_freq; + int if_freq_off; + int chest_freq; + int chest_time; + int no_timing_correction; + int nb_antennas_rx; + int nb_antennas_tx; + int threequarter_fs; + int N_RB_DL; + int ssb_start_subcarrier; } nrUE_params_t; extern uint64_t get_nrUE_optmask(void); extern uint64_t set_nrUE_optmask(uint64_t bitmask); diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index d9aedd768c..cf6ef56ea4 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -38,11 +38,12 @@ extern "C" #endif /* help strings definition for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */ #define CONFIG_HLP_RFCFGF "Configuration file for front-end (e.g. LMS7002M)\n" -#define CONFIG_HLP_SPLIT73 "Split 7.3 (below rate matching) option: ::" +#define CONFIG_HLP_SPLIT73 "Split 7.3 (below rate matching) option: ::\n" #define CONFIG_HLP_TPOOL "Thread pool configuration: \n\ - default no pool (runs in calling thread),\n\ list of cores, comma separated (negative value is no core affinity)\n\ - example: -1,3 launches two working threads one floating, the second set on core 3" + example: -1,3 launches two working threads one floating, the second set on core 3\n\ + default 8 floating threads\n\ + use N for no pool (runs in calling thread) recommended with rfsim.\n" #define CONFIG_HLP_ULMAXE "set the eNodeB max ULSCH erros\n" #define CONFIG_HLP_CALUER "set UE RX calibration\n" #define CONFIG_HLP_CALUERM "" 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 d429bf43ba..87fe5b82bc 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 @@ -21,6 +21,7 @@ #include "stddef.h" #include "platform_types.h" #include "fapi_nr_ue_constants.h" +#include "PHY/impl_defs_top.h" #include "PHY/impl_defs_nr.h" #include "common/utils/nr/nr_common.h" @@ -116,7 +117,8 @@ typedef struct { } fapi_nr_pdsch_pdu_t; typedef struct { - uint8_t* pdu; // 3bytes + bool decoded_pdu; + uint8_t pdu[3]; uint8_t additional_bits; uint8_t ssb_index; uint8_t ssb_length; @@ -390,8 +392,6 @@ typedef struct { } fapi_nr_ul_config_request_pdu_t; typedef struct { - //uint16_t sfn; - //uint16_t slot; uint16_t sfn; uint16_t slot; uint8_t number_pdus; @@ -423,9 +423,6 @@ typedef struct { typedef struct { fapi_nr_dl_config_dci_dl_pdu_rel15_t dci_config_rel15; } fapi_nr_dl_config_dci_pdu; -typedef struct{ - uint8_t aperiodicSRS_ResourceTrigger; -} fapi_nr_dl_srs_config_t; typedef enum{vrb_to_prb_mapping_non_interleaved = 0, vrb_to_prb_mapping_interleaved = 1} vrb_to_prb_mapping_t; @@ -462,7 +459,6 @@ typedef struct { uint16_t dmrs_ports; uint8_t n_front_load_symb; uint8_t tci_state; - fapi_nr_dl_srs_config_t srs_config; uint8_t cbgti; uint8_t codeBlockGroupFlushIndicator; // to be check the fields needed to L1 with NR_DL_UE_HARQ_t and NR_UE_DLSCH_t @@ -483,6 +479,7 @@ typedef struct { uint8_t nscid; uint16_t dlDmrsScramblingId; uint16_t pduBitmap; + uint32_t k1_feedback; } fapi_nr_dl_config_dlsch_pdu_rel15_t; typedef struct { diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 32e5647b69..65d3f86f7a 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -202,7 +202,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) // create shortcuts NR_DL_FRAME_PARMS *const fp = &ue->frame_parms; NR_UE_COMMON *const common_vars = &ue->common_vars; - NR_UE_PBCH **const pbch_vars = ue->pbch_vars; NR_UE_PRACH **const prach_vars = ue->prach_vars; NR_UE_CSI_IM **const csiim_vars = ue->csiim_vars; NR_UE_CSI_RS **const csirs_vars = ue->csirs_vars; @@ -357,7 +356,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) // DLSCH for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) { prach_vars[gNB_id] = (NR_UE_PRACH *)malloc16_clear(sizeof(NR_UE_PRACH)); - pbch_vars[gNB_id] = (NR_UE_PBCH *)malloc16_clear(sizeof(NR_UE_PBCH)); csiim_vars[gNB_id] = (NR_UE_CSI_IM *)malloc16_clear(sizeof(NR_UE_CSI_IM)); csirs_vars[gNB_id] = (NR_UE_CSI_RS *)malloc16_clear(sizeof(NR_UE_CSI_RS)); srs_vars[gNB_id] = (NR_UE_SRS *)malloc16_clear(sizeof(NR_UE_SRS)); @@ -476,7 +474,6 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) free_and_zero(ue->csirs_vars[gNB_id]); free_and_zero(ue->srs_vars[gNB_id]); - free_and_zero(ue->pbch_vars[gNB_id]); free_and_zero(ue->prach_vars[gNB_id]); } @@ -523,7 +520,6 @@ void free_nr_ue_dl_harq(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PROCESSES for (int j=0; j < 2; j++) { for (int i=0; iif_inst && ue->if_inst->dl_indication) { ue->if_inst->dl_indication(&dl_indication, NULL); - } else { - free(rx_ind); } return 0; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index db6a15213c..470164817b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -51,15 +51,8 @@ #define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384 //#define OAI_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX -static uint64_t nb_total_decod =0; -static uint64_t nb_error_decod =0; - static extended_kpi_ue kpiStructure = {0}; -notifiedFIFO_t freeBlocks_dl; -notifiedFIFO_elt_t *msgToPush_dl; -int nbDlProcessing =0; - extended_kpi_ue* getKPIUE(void) { return &kpiStructure; } @@ -77,7 +70,7 @@ void nr_dlsch_unscrambling(int16_t *llr, uint32_t size, uint8_t q, uint32_t Nid, nr_codeword_unscrambling(llr, size, q, Nid, n_RNTI); } -bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool last, notifiedFIFO_t *nf_p) { +bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool last, notifiedFIFO_t *nf_p, int b_size, uint8_t b[b_size], int *num_seg_ok, UE_nr_rxtx_proc_t *proc) { ldpcDecode_ue_t *rdata = (ldpcDecode_ue_t*) NotifiedFifoData(req); NR_DL_UE_HARQ_t *harq_process = rdata->harq_process; NR_UE_DLSCH_t *dlsch = (NR_UE_DLSCH_t *) rdata->dlsch; @@ -90,10 +83,11 @@ bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool bool decodeSuccess = (rdata->decodeIterations < (1+dlsch->max_ldpc_iterations)); if (decodeSuccess) { - memcpy(harq_process->b+rdata->offset, + memcpy(b+rdata->offset, harq_process->c[r], rdata->Kr_bytes - (harq_process->F>>3) -((harq_process->C>1)?3:0)); + (*num_seg_ok)++; } else { if ( !last ) { int nb=abortTpoolJob(&get_nrUE_params()->Tpool, req->key); @@ -111,7 +105,20 @@ bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool kpiStructure.dl_mcs = dlsch->dlsch_config.mcs; kpiStructure.nofRBs = dlsch->dlsch_config.number_rbs; - if (decodeSuccess) { + if (*num_seg_ok == harq_process->C) { + if (harq_process->C > 1) { + /* check global CRC */ + int A = dlsch->dlsch_config.TBS; + int crc_length = A > 3824 ? 3 : 2; + int crc_type = A > 3824 ? CRC24_A : CRC16; + if (!check_crc(b, A + crc_length*8, 0 /* F - unused */, crc_type)) { + harq_process->ack = 0; + dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations + 1; + LOG_E(PHY, " Frame %d.%d LDPC global CRC fails, but individual LDPC CRC succeeded. %d segs\n", proc->frame_rx, proc->nr_slot_rx, harq_process->C); + LOG_D(PHY, "DLSCH received nok \n"); + return true; //stop + } + } //LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for nr_slot_rx %d TBS %d mcs %d nb_rb %d harq_process->round %d\n", // phy_vars_ue->Mod_id,nr_slot_rx,harq_process->TBS,harq_process->mcs,harq_process->nb_rb, harq_process->round); harq_process->status = SCH_IDLE; @@ -277,7 +284,7 @@ void nr_processDLSegment(void* arg) { if (no_iteration_ldpc > dlsch->max_ldpc_iterations) no_iteration_ldpc = dlsch->max_ldpc_iterations; } else { - LOG_D(PHY,"CRC NOT OK\n"); + LOG_I(PHY,"%d.%d CRC NOT OK\n",rdata->proc->frame_rx,rdata->proc->nr_slot_rx); no_iteration_ldpc = dlsch->max_ldpc_iterations + 1; } @@ -287,12 +294,6 @@ void nr_processDLSegment(void* arg) { rdata->decodeIterations = no_iteration_ldpc; - nb_total_decod++; - - if (no_iteration_ldpc > dlsch->max_ldpc_iterations) { - nb_error_decod++; - } - for (int m=0; m < Kr>>3; m ++) { harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; } @@ -311,7 +312,9 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, uint32_t frame, uint16_t nb_symb_sch, uint8_t nr_slot_rx, - uint8_t harq_pid) { + uint8_t harq_pid, + int b_size, + uint8_t b[b_size]) { uint32_t A,E; uint32_t G; uint32_t ret,offset; @@ -476,6 +479,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, rdata->offset = offset; rdata->dlsch = dlsch; rdata->dlsch_id = 0; + rdata->proc = proc; reset_meas(&rdata->ts_deinterleave); reset_meas(&rdata->ts_rate_unmatch); reset_meas(&rdata->ts_ldpc_decode); @@ -486,6 +490,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0)); ////////////////////////////////////////////////////////////////////////////////////////// } + int num_seg_ok = 0; for (r=0; rTpool); if (req == NULL) @@ -493,7 +498,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, bool last = false; if (r == nbDecode - 1) last = true; - bool stop = nr_ue_postDecode(phy_vars_ue, req, last, &nf); + bool stop = nr_ue_postDecode(phy_vars_ue, req, last, &nf, b_size, b, &num_seg_ok, proc); delNotifiedFIFO_elt(req); if (stop) break; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 061eede6dd..da99ba7405 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -155,12 +155,11 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini proc,i,i-pbch_initial_symbol,temp_ptr->i_ssb,temp_ptr->n_hf,rxdataF); stop_meas(&ue->dlsch_channel_estimation_stats); - fapiPbch_t result; + fapiPbch_t result = {0}; ret = nr_rx_pbch(ue, proc, estimateSz, dl_ch_estimates, - ue->pbch_vars[0], frame_parms, temp_ptr->i_ssb, SISO, @@ -188,11 +187,6 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini // openair_daq_vars.dlsch_transmission_mode = (pbch_tx_ant>1) ? 2 : 1; - // flip byte endian on 24-bits for MIB - // dummy = ue->pbch_vars[0]->decoded_output[0]; - // ue->pbch_vars[0]->decoded_output[0] = ue->pbch_vars[0]->decoded_output[2]; - // ue->pbch_vars[0]->decoded_output[2] = dummy; - #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"[UE%d] Initial sync: pbch decoded sucessfully\n",ue->Mod_id); #endif @@ -447,8 +441,6 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, // send sync status to higher layers later when timing offset converge to target timing - ue->pbch_vars[0]->pdu_errors_conseq=0; - } @@ -466,10 +458,6 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, frame_parms->Nid_cell,frame_parms->frame_type); #endif - ue->pbch_vars[0]->pdu_errors_last=ue->pbch_vars[0]->pdu_errors; - ue->pbch_vars[0]->pdu_errors++; - ue->pbch_vars[0]->pdu_errors_conseq++; - } // gain control diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index 0c2149e997..2fa9ca37ef 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -302,8 +302,7 @@ void nr_pbch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, #endif } -static void nr_pbch_unscrambling(NR_UE_PBCH *pbch, - int16_t *demod_pbch_e, +static void nr_pbch_unscrambling(int16_t *demod_pbch_e, uint16_t Nid, uint8_t nushift, uint16_t M, @@ -311,7 +310,8 @@ static void nr_pbch_unscrambling(NR_UE_PBCH *pbch, uint8_t bitwise, uint32_t unscrambling_mask, uint32_t pbch_a_prime, - uint32_t *pbch_a_interleaved) { + uint32_t *pbch_a_interleaved) +{ uint8_t reset, offset; uint32_t x1 = 0, x2 = 0, s = 0; uint8_t k=0; @@ -384,17 +384,17 @@ unsigned char sign(int8_t x) { uint8_t pbch_deinterleaving_pattern[32] = {28,0,31,30,7,29,25,27,5,8,24,9,10,11,12,13,1,4,3,14,15,16,17,2,26,18,19,20,21,22,6,23}; -int nr_rx_pbch( PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - int estimateSz, struct complex16 dl_ch_estimates [][estimateSz], - NR_UE_PBCH *nr_ue_pbch_vars, - NR_DL_FRAME_PARMS *frame_parms, - uint8_t i_ssb, - MIMO_mode_t mimo_mode, - nr_phy_data_t *phy_data, - fapiPbch_t *result, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) { - +int nr_rx_pbch(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + int estimateSz, + struct complex16 dl_ch_estimates [][estimateSz], + NR_DL_FRAME_PARMS *frame_parms, + uint8_t i_ssb, + MIMO_mode_t mimo_mode, + nr_phy_data_t *phy_data, + fapiPbch_t *result, + c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) +{ int max_h=0; int symbol; //uint8_t pbch_a[64]; @@ -456,7 +456,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, } #ifdef DEBUG_PBCH - LOG_I(PHY,"[PHY] PBCH log2_maxh = %d (%d)\n",nr_ue_pbch_vars->log2_maxh,max_h); + LOG_I(PHY,"[PHY] PBCH log2_maxh = %d (%d)\n", log2_maxh, max_h); #endif __attribute__ ((aligned(32))) struct complex16 rxdataF_comp[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL]; nr_pbch_channel_compensation(rxdataF_ext, @@ -464,7 +464,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, nb_re, rxdataF_comp, frame_parms, - log2_maxh); // log2_maxh+I0_shift + log2_maxh); // log2_maxh+I0_shift /*if (frame_parms->nb_antennas_rx > 1) pbch_detection_mrc(frame_parms, @@ -504,16 +504,25 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, uint32_t unscrambling_mask = (Lmax==64)?0x100006D:0x1000041; uint32_t pbch_a_interleaved=0; uint32_t pbch_a_prime=0; - nr_pbch_unscrambling(nr_ue_pbch_vars, pbch_e_rx, frame_parms->Nid_cell, nushift, M, NR_POLAR_PBCH_E, + nr_pbch_unscrambling(pbch_e_rx, frame_parms->Nid_cell, nushift, M, NR_POLAR_PBCH_E, 0, 0, pbch_a_prime, &pbch_a_interleaved); //polar decoding de-rate matching uint64_t tmp=0; decoderState = polar_decoder_int16(pbch_e_rx,(uint64_t *)&tmp,0, NR_POLAR_PBCH_MESSAGE_TYPE, NR_POLAR_PBCH_PAYLOAD_BITS, NR_POLAR_PBCH_AGGREGATION_LEVEL); - pbch_a_prime=tmp; - if(decoderState) - return(decoderState); + pbch_a_prime = tmp; + nr_downlink_indication_t dl_indication; + fapi_nr_rx_indication_t rx_ind = {0}; + uint16_t number_pdus = 1; + + if(decoderState) { + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, phy_data); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, NULL, NULL); + if (ue->if_inst && ue->if_inst->dl_indication) + ue->if_inst->dl_indication(&dl_indication, NULL); + return(decoderState); + } // printf("polar decoder output 0x%08x\n",pbch_a_prime); // Decoder reversal uint32_t a_reversed=0; @@ -526,7 +535,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, M = (Lmax == 64)? (NR_POLAR_PBCH_PAYLOAD_BITS - 6) : (NR_POLAR_PBCH_PAYLOAD_BITS - 3); nushift = ((pbch_a_prime>>24)&1) ^ (((pbch_a_prime>>6)&1)<<1); pbch_a_interleaved=0; - nr_pbch_unscrambling(nr_ue_pbch_vars, pbch_e_rx, frame_parms->Nid_cell, nushift, M, NR_POLAR_PBCH_PAYLOAD_BITS, + nr_pbch_unscrambling(pbch_e_rx, frame_parms->Nid_cell, nushift, M, NR_POLAR_PBCH_PAYLOAD_BITS, 1, unscrambling_mask, pbch_a_prime, &pbch_a_interleaved); //printf("nushift %d sfn 3rd %d 2nd %d", nushift,((pbch_a_prime>>6)&1), ((pbch_a_prime>>24)&1) ); //payload deinterleaving @@ -577,17 +586,12 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, } #endif - nr_downlink_indication_t dl_indication; - fapi_nr_rx_indication_t *rx_ind=calloc(sizeof(*rx_ind),1); - uint16_t number_pdus = 1; - nr_fill_dl_indication(&dl_indication, NULL, rx_ind, proc, ue, phy_data); - nr_fill_rx_indication(rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc,(void *)result); + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, phy_data); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, (void *)result, NULL); if (ue->if_inst && ue->if_inst->dl_indication) ue->if_inst->dl_indication(&dl_indication, NULL); - else - free(rx_ind); // dl_indication would free(), so free() here if not called return 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 0d6c334c45..b20dbf8483 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -205,7 +205,9 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, uint32_t frame, uint16_t nb_symb_sch, uint8_t nr_slot_rx, - uint8_t harq_pid); + uint8_t harq_pid, + int b_size, + uint8_t b[b_size]); int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, NR_UE_ULSCH_t *ulsch, @@ -285,7 +287,6 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, const int estimateSz, struct complex16 dl_ch_estimates[][estimateSz], - NR_UE_PBCH *nr_ue_pbch_vars, NR_DL_FRAME_PARMS *frame_parms, uint8_t i_ssb, MIMO_mode_t mimo_mode, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index dc09714da9..811fa7711b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -119,8 +119,6 @@ typedef struct { uint32_t TBS; /// The payload + CRC size in bits uint32_t B; - /// Pointer to the payload - uint8_t *b; /// Pointers to transport block segments uint8_t **c; /// soft bits for each received segment ("d"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) diff --git a/openair1/PHY/TOOLS/nr_phy_qt_scope.cpp b/openair1/PHY/TOOLS/nr_phy_qt_scope.cpp index fecfefd131..5aecc3906b 100644 --- a/openair1/PHY/TOOLS/nr_phy_qt_scope.cpp +++ b/openair1/PHY/TOOLS/nr_phy_qt_scope.cpp @@ -317,6 +317,34 @@ void CIRPlot::timerEvent(QTimerEvent *event) this->series->replace(points); } +void CIRPlotUE::timerEvent(QTimerEvent *event) +{ + if (!this->isVisible()) + return; + + scopeGraphData_t *data = this->valueProvider->getPlotValue(); + if (data) { + this->data = (complex16 *)(data + 1); + this->len = data->lineSz; + QVector points(this->len); + float maxY = this->axisY->max(); + + for (int i = 0; i < this->len / 2; i++) { + float value = SquaredNorm(this->data[i + this->len / 2]); + points[i] = QPointF(i - this->len / 2, value); + maxY = std::max(maxY, value); + } + for (int i = 0; i < this->len / 2; i++) { + float value = SquaredNorm(this->data[i]); + points[i + this->len / 2] = QPointF(i, value); + maxY = std::max(maxY, value); + } + + this->axisY->setMax(maxY); + this->series->replace(points); + } +} + LLRPlot::LLRPlot(int16_t *data, int len) : data(data), len(len) { this->legend()->hide(); @@ -361,6 +389,28 @@ void LLRPlot::timerEvent(QTimerEvent *event) this->series->replace(points); } +void LLRPlotUE::timerEvent(QTimerEvent *event) +{ + if (!this->isVisible()) + return; + + scopeGraphData_t *data = this->valueProvider->getPlotValue(); + if (data) { + this->data = (int16_t *)(data + 1); + this->len = data->lineSz; + QVector points(this->len); + int maxY = this->axisY->max(); + + for (int i = 0; i < this->len; i++) { + points[i] = QPointF(i, this->data[i]); + maxY = std::max(maxY, abs(this->data[i])); + } + + this->axisY->setRange(-maxY, maxY); + this->series->replace(points); + } +} + IQPlot::IQPlot(complex16 *data, int len) : data(data), len(len) { this->legend()->hide(); @@ -407,6 +457,32 @@ void IQPlot::timerEvent(QTimerEvent *event) this->series->replace(points); } +void IQPlotUE::timerEvent(QTimerEvent *event) +{ + if (!this->isVisible()) + return; + + scopeGraphData_t *data = this->valueProvider->getPlotValue(); + if (data) { + this->data = (complex16 *)(data + 1); + this->len = data->lineSz; + QVector points(this->len); + int maxX = this->axisX->max(); + int maxY = this->axisY->max(); + + for (int i = 0; i < this->len; i++) { + points[i] = QPointF(this->data[i].r, this->data[i].i); + + maxX = std::max(maxX, abs(this->data[i].r)); + maxY = std::max(maxY, abs(this->data[i].i)); + } + + this->axisX->setRange(-maxX, maxX); + this->axisY->setRange(-maxY, maxY); + this->series->replace(points); + } +} + KPIPlot::KPIPlot(ValueProvider *valueProvider, float *limits) : valueProvider(valueProvider), limits(limits) { this->series = new QLineSeries(); @@ -815,11 +891,42 @@ float PainterWidgetUE::getValue() case PlotTypeUE::timingAdvance: return (float)this->ue->timing_advance; + default: return 0; } } +scopeGraphData_t *PainterWidgetUE::getPlotValue() +{ + scopeData_t *scope = (scopeData_t *)this->ue->scopeData; + scopeGraphData_t **data = (scopeGraphData_t **)scope->liveData; + switch (this->plotType) { + case PlotTypeUE::CIR: + return data[pbchDlChEstimateTime]; + + case PlotTypeUE::pbchLLR: + return data[pbchLlr]; + case PlotTypeUE::pbchIQ: + return data[pbchRxdataF_comp]; + + case PlotTypeUE::pdcchLLR: + return data[pdcchLlr]; + + case PlotTypeUE::pdcchIQ: + return data[pdcchRxdataF_comp]; + + case PlotTypeUE::pdschLLR: + return data[pdschLlr]; + + case PlotTypeUE::pdschIQ: + return data[pdschRxdataF_comp]; + + default: + return nullptr; + } +} + /* @UE Class: this function is called when a resize event is detected, then the widget will be adjusted accordignly. */ void PainterWidgetUE::resizeEvent(QResizeEvent *event) { @@ -890,7 +997,7 @@ void PainterWidgetUE::makeConnections(int type) this->comboBox->setCurrentIndex(static_cast(PlotTypeUE::empty)); break; } - newChart = new LLRPlot((int16_t *)(data[pbchLlr] + 1), data[pbchLlr]->lineSz); + newChart = new LLRPlotUE((int16_t *)(data[pbchLlr] + 1), data[pbchLlr]->lineSz, this); break; } case PlotTypeUE::pbchIQ: { @@ -900,7 +1007,7 @@ void PainterWidgetUE::makeConnections(int type) this->comboBox->setCurrentIndex(static_cast(PlotTypeUE::empty)); break; } - newChart = new IQPlot((complex16 *)(data[pbchRxdataF_comp] + 1), data[pbchRxdataF_comp]->lineSz); + newChart = new IQPlotUE((complex16 *)(data[pbchRxdataF_comp] + 1), data[pbchRxdataF_comp]->lineSz, this); break; } case PlotTypeUE::pdcchLLR: { @@ -910,7 +1017,7 @@ void PainterWidgetUE::makeConnections(int type) this->comboBox->setCurrentIndex(static_cast(PlotTypeUE::empty)); break; } - newChart = new LLRPlot((int16_t *)(data[pdcchLlr] + 1), data[pdcchLlr]->lineSz); + newChart = new LLRPlotUE((int16_t *)(data[pdcchLlr] + 1), data[pdcchLlr]->lineSz, this); break; } case PlotTypeUE::pdcchIQ: { @@ -920,7 +1027,7 @@ void PainterWidgetUE::makeConnections(int type) this->comboBox->setCurrentIndex(static_cast(PlotTypeUE::empty)); break; } - newChart = new IQPlot((complex16 *)(data[pdcchRxdataF_comp] + 1), data[pdcchRxdataF_comp]->lineSz); + newChart = new IQPlotUE((complex16 *)(data[pdcchRxdataF_comp] + 1), data[pdcchRxdataF_comp]->lineSz, this); break; } case PlotTypeUE::pdschLLR: { @@ -930,7 +1037,7 @@ void PainterWidgetUE::makeConnections(int type) this->comboBox->setCurrentIndex(static_cast(PlotTypeUE::empty)); break; } - newChart = new LLRPlot((int16_t *)(data[pdschLlr] + 1), data[pdschLlr]->lineSz); + newChart = new LLRPlotUE((int16_t *)(data[pdschLlr] + 1), data[pdschLlr]->lineSz, this); break; } case PlotTypeUE::pdschIQ: { @@ -940,7 +1047,7 @@ void PainterWidgetUE::makeConnections(int type) this->comboBox->setCurrentIndex(static_cast(PlotTypeUE::empty)); break; } - newChart = new IQPlot((complex16 *)(data[pdschRxdataF_comp] + 1), data[pdschRxdataF_comp]->lineSz); + newChart = new IQPlotUE((complex16 *)(data[pdschRxdataF_comp] + 1), data[pdschRxdataF_comp]->lineSz, this); break; } @@ -1147,6 +1254,7 @@ void nrUEinitQtScope(PHY_VARS_NR_UE *ue) scope->liveData = calloc(sizeof(scopeGraphData_t *), UEdataTypeNumberOfItems); scope->copyData = UEcopyData; + UEcopyDataMutexInit(); ue->scopeData = scope; diff --git a/openair1/PHY/TOOLS/nr_phy_qt_scope.h b/openair1/PHY/TOOLS/nr_phy_qt_scope.h index f10fef9d61..8a00d5fa96 100644 --- a/openair1/PHY/TOOLS/nr_phy_qt_scope.h +++ b/openair1/PHY/TOOLS/nr_phy_qt_scope.h @@ -91,6 +91,14 @@ class ValueProvider { virtual float getValue() = 0; }; +class ValueProviderUE : public ValueProvider { + public: + /// This pure virtual function is meant to provide the graph values to be plotted + virtual scopeGraphData_t *getPlotValue() { + return nullptr; + } +}; + /// An editable GUI field for a dialog box to set certain KPI configurations class ConfigBoxFloat : public QLineEdit { Q_OBJECT @@ -206,7 +214,6 @@ class CIRPlot : public QChart { /// \param event Pointer to the timer event virtual void timerEvent(QTimerEvent *event) override; - private: /// Pointer to the CIR data complex16 *data; @@ -223,6 +230,21 @@ class CIRPlot : public QChart { QValueAxis *axisY; }; +class CIRPlotUE : public CIRPlot { + Q_OBJECT + + public: + CIRPlotUE(complex16 *data, int len, ValueProviderUE *valueProvider) : CIRPlot(data, len), valueProvider(valueProvider) {} + + protected: + /// This function is triggered when the own timer expires. It updates the plotted CIR + /// \param event Pointer to the timer event + virtual void timerEvent(QTimerEvent *event) override; + + private: + ValueProviderUE *valueProvider; +}; + /// Chart class for plotting LLRs class LLRPlot : public QChart { Q_OBJECT @@ -238,7 +260,6 @@ class LLRPlot : public QChart { /// \param event Pointer to the timer event virtual void timerEvent(QTimerEvent *event) override; - private: /// Pointer to the LLR data int16_t *data; @@ -255,6 +276,21 @@ class LLRPlot : public QChart { QValueAxis *axisY; }; +class LLRPlotUE : public LLRPlot { + Q_OBJECT + + public: + LLRPlotUE(int16_t *data, int len, ValueProviderUE *valueProvider) : LLRPlot(data, len), valueProvider(valueProvider) {} + + protected: + /// This function is triggered when the own timer expires. It updates the plotted I/Q constellation diagram + /// \param event Pointer to the timer event + virtual void timerEvent(QTimerEvent *event) override; + + private: + ValueProviderUE *valueProvider; +}; + /// Chart class for plotting the I/Q constellation diagram class IQPlot : public QChart { Q_OBJECT @@ -270,7 +306,6 @@ class IQPlot : public QChart { /// \param event Pointer to the timer event virtual void timerEvent(QTimerEvent *event) override; - private: /// Pointer to the I/Q data complex16 *data; @@ -287,6 +322,22 @@ class IQPlot : public QChart { QValueAxis *axisY; }; +class IQPlotUE : public IQPlot { + Q_OBJECT + + public: + IQPlotUE(complex16 *data, int len, ValueProviderUE *valueProvider) : IQPlot(data, len), valueProvider(valueProvider) {} + + protected: + /// This function is triggered when the own timer expires. It updates the plotted I/Q constellation diagram + /// \param event Pointer to the timer event + virtual void timerEvent(QTimerEvent *event) override; + + private: + /// Pointer to an instance of a class that implements the ValueProvider interface + ValueProviderUE *valueProvider; +}; + /// Generic class for plotting KPI values with min., max. and average bars class KPIPlot : public QChart { Q_OBJECT @@ -422,7 +473,7 @@ class PainterWidgetGnb : public QWidget, public ValueProvider { }; /// Widget showing one selectable UE KPI -class PainterWidgetUE : public QWidget, public ValueProvider { +class PainterWidgetUE : public QWidget, public ValueProviderUE { Q_OBJECT public: @@ -435,6 +486,8 @@ class PainterWidgetUE : public QWidget, public ValueProvider { /// This function provides the current KPI value to be plotted virtual float getValue() override; + virtual scopeGraphData_t *getPlotValue() override; + protected: /// This function is called to change the widget size /// \param event Pointer to the resize event diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index 206ed490e5..17141c7158 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -1137,8 +1137,6 @@ static void *nrUEscopeThread(void *arg) { } #endif -pthread_mutex_t UEcopyDataMutex; - STATICFORXSCOPE void nrUEinitScope(PHY_VARS_NR_UE *ue) { AssertFatal(ue->scopeData=malloc(sizeof(scopeData_t)),""); @@ -1148,8 +1146,8 @@ STATICFORXSCOPE void nrUEinitScope(PHY_VARS_NR_UE *ue) #ifndef WEBSRVSCOPE pthread_t forms_thread; threadCreate(&forms_thread, nrUEscopeThread, ue, "scope", -1, OAI_PRIORITY_RT_LOW); + UEcopyDataMutexInit(); #endif - pthread_mutex_init(&UEcopyDataMutex, NULL); } void nrscope_autoinit(void *dataptr) { diff --git a/openair1/PHY/TOOLS/phy_scope_interface.c b/openair1/PHY/TOOLS/phy_scope_interface.c index b567e96b03..6dfcc36c75 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.c +++ b/openair1/PHY/TOOLS/phy_scope_interface.c @@ -35,9 +35,16 @@ #include "phy_scope_interface.h" #define SOFTSCOPE_ENDFUNC_IDX 0 +#define THREAD_MEM 4 static loader_shlibfunc_t scope_fdesc[]= {{"end_forms",NULL}}; +pthread_mutex_t UEcopyDataMutex; + +int UEcopyDataMutexInit(void) { + return pthread_mutex_init(&UEcopyDataMutex, NULL); +} + int load_softscope(char *exectype, void *initarg) { char libname[64]; sprintf(libname,"%.10sscope",exectype); @@ -56,16 +63,19 @@ int end_forms(void) { void UEcopyData(PHY_VARS_NR_UE *ue, enum UEdataType type, void *dataIn, int elementSz, int colSz, int lineSz) { // Local static copy of the scope data bufs // The active data buf is alterned to avoid interference between the Scope thread (display) and the Rx thread (data input) - // Index of "2" could be set to the number of Rx threads + 1 - static scopeGraphData_t *copyDataBufs[UEdataTypeNumberOfItems][2] = {0}; + // Index of THREAD_MEM could be set to the number of Rx threads + 1. Rx slots could run asynchronous to each other. + // THREAD_MEM = 4 slot process running in parallel is an assumption. THREAD_MEM can be increased if scope appears inconsistent. + static scopeGraphData_t *copyDataBufs[UEdataTypeNumberOfItems][THREAD_MEM] = {0}; static int copyDataBufsIdx[UEdataTypeNumberOfItems] = {0}; scopeData_t *tmp = (scopeData_t *)ue->scopeData; if (tmp) { - // Begin of critical zone between UE Rx threads that might copy new data at the same time: might require a mutex - int newCopyDataIdx = (copyDataBufsIdx[type]==0)?1:0; + // Begin of critical zone between UE Rx threads that might copy new data at the same time: + pthread_mutex_lock(&UEcopyDataMutex); + int newCopyDataIdx = (copyDataBufsIdx[type]<(THREAD_MEM-1))?copyDataBufsIdx[type]+1:0; copyDataBufsIdx[type] = newCopyDataIdx; + pthread_mutex_unlock(&UEcopyDataMutex); // End of critical zone between UE Rx threads // New data will be copied in a different buffer than the live one diff --git a/openair1/PHY/TOOLS/phy_scope_interface.h b/openair1/PHY/TOOLS/phy_scope_interface.h index b6d4480762..19395891ad 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.h +++ b/openair1/PHY/TOOLS/phy_scope_interface.h @@ -31,15 +31,21 @@ */ #ifndef __PHY_SCOPE_INTERFACE_H__ #define __PHY_SCOPE_INTERFACE_H__ + +#ifdef __cplusplus +#include +#define _Atomic(X) std::atomic< X > +#endif + #include #include typedef struct { - uint32_t nb_total; - uint32_t nb_nack; - uint32_t blockSize; // block size, to be used for throughput calculation - uint16_t nofRBs; - uint8_t dl_mcs; + _Atomic(uint32_t) nb_total; + _Atomic(uint32_t) nb_nack; + _Atomic(uint32_t) blockSize; // block size, to be used for throughput calculation + _Atomic(uint16_t) nofRBs; + _Atomic(uint8_t ) dl_mcs; } extended_kpi_ue; typedef struct { @@ -80,6 +86,7 @@ typedef struct { int load_softscope(char *exectype, void *initarg); int end_forms(void) ; +int UEcopyDataMutexInit(void); void UEcopyData(PHY_VARS_NR_UE *ue, enum UEdataType type, void *dataIn, int elementSz, int colSz, int lineSz); #define UEscopeCopy(ue, type, ...) if(ue->scopeData) ((scopeData_t*)ue->scopeData)->copyData(ue, type, ##__VA_ARGS__); diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 1c248bc4a9..71853765af 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -823,6 +823,8 @@ typedef struct processingData_L1tx { uint16_t num_pdsch_slot; int num_dl_pdcch; int num_ul_pdcch; + /* a reference to the sched_response, to release it when not needed anymore */ + int sched_response_id; } processingData_L1tx_t; #endif diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 9ba7233770..1543c81e00 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -32,6 +32,10 @@ #ifndef __PHY_DEFS_NR_UE__H__ #define __PHY_DEFS_NR_UE__H__ +#ifdef __cplusplus +#include +#define _Atomic(X) std::atomic< X > +#endif #include "defs_nr_common.h" #include "CODING/nrPolar_tools/nr_polar_pbch_defs.h" @@ -316,17 +320,6 @@ typedef struct { #define PBCH_A 24 -typedef struct { - /// \brief Total number of PDU errors. - uint32_t pdu_errors; - /// \brief Total number of PDU errors 128 frames ago. - uint32_t pdu_errors_last; - /// \brief Total number of consecutive PDU errors. - uint32_t pdu_errors_conseq; - /// \brief FER (in percent) . - //uint32_t pdu_fer; -} NR_UE_PBCH; - typedef struct { int16_t amp; bool active; @@ -385,9 +378,6 @@ typedef struct { uint8_t CC_id; /// \brief Mapping of CC_id antennas to cards openair0_rf_map rf_map; - //uint8_t local_flag; - /// \brief Indicator of current run mode of UE (normal_txrx, rx_calib_ue, no_L2_connect, debug_prach) - runmode_t mode; /// \brief Indicator that UE should perform band scanning int UE_scan; /// \brief Indicator that UE should perform coarse scanning around carrier @@ -402,8 +392,6 @@ typedef struct { int is_synchronized; /// \brief Target gNB Nid_cell when UE is resynchronizing int target_Nid_cell; - /// \brief Indicator that UE lost frame synchronization - int lost_sync; /// Data structure for UE process scheduling UE_nr_proc_t proc; /// Flag to indicate the UE shouldn't do timing correction at all @@ -444,7 +432,6 @@ typedef struct { fapi_nr_config_request_t nrUE_config; nr_synch_request_t synch_request; - NR_UE_PBCH *pbch_vars[NUMBER_OF_CONNECTED_gNB_MAX]; NR_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_gNB_MAX]; NR_UE_CSI_IM *csiim_vars[NUMBER_OF_CONNECTED_gNB_MAX]; NR_UE_CSI_RS *csirs_vars[NUMBER_OF_CONNECTED_gNB_MAX]; @@ -655,7 +642,7 @@ typedef struct { SLIST_HEAD(ral_thresholds_lte_poll_s, ral_threshold_phy_t) ral_thresholds_lte_polled[RAL_LINK_PARAM_LTE_MAX]; #endif int dl_errors; - int dl_stats[8]; + _Atomic(int) dl_stats[16]; void* scopeData; // Pointers to hold PDSCH data only for phy simulators void *phy_sim_rxdataF; @@ -664,6 +651,10 @@ typedef struct { void *phy_sim_pdsch_rxdataF_comp; void *phy_sim_pdsch_dl_ch_estimates; void *phy_sim_pdsch_dl_ch_estimates_ext; + uint8_t *phy_sim_dlsch_b; + notifiedFIFO_t phy_config_ind; + notifiedFIFO_t *tx_resume_ind_fifo[NR_MAX_SLOTS_PER_FRAME]; + int tx_wait_for_dlsch[NR_MAX_SLOTS_PER_FRAME]; } PHY_VARS_NR_UE; typedef struct nr_phy_data_tx_s { @@ -682,6 +673,8 @@ typedef struct nr_rxtx_thread_data_s { UE_nr_rxtx_proc_t proc; PHY_VARS_NR_UE *UE; int writeBlockSize; + nr_phy_data_t phy_data; + int tx_wait_for_dlsch; } nr_rxtx_thread_data_t; typedef struct LDPCDecode_ue_s { @@ -707,6 +700,7 @@ typedef struct LDPCDecode_ue_s { time_stats_t ts_deinterleave; time_stats_t ts_rate_unmatch; time_stats_t ts_ldpc_decode; + UE_nr_rxtx_proc_t *proc; } ldpcDecode_ue_t; #include "SIMULATION/ETH_TRANSPORT/defs.h" diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h index 6afbd1bf2b..679fd34a49 100644 --- a/openair1/PHY/impl_defs_top.h +++ b/openair1/PHY/impl_defs_top.h @@ -270,7 +270,7 @@ /* FFS_NR_TODO it defines ue capability which is the number of slots */ /* - between reception of pdsch and tarnsmission of its acknowlegment */ /* - between reception of un uplink grant and its related transmission */ -#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (4) +#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (3) #ifndef NO_RAT_NR #define DURATION_RX_TO_TX (NR_UE_CAPABILITY_SLOT_RX_TO_TX) /* for NR this will certainly depends to such UE capability which is not yet defined */ diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 43223906d5..6f644c4ba5 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -35,6 +35,7 @@ #include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "PHY/NR_TRANSPORT/nr_dci.h" #include "nfapi/oai_integration/vendor_ext.h" +#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h" extern int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req); extern int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req); @@ -131,10 +132,10 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO) { // copy data from L2 interface into L1 structures module_id_t Mod_id = Sched_INFO->module_id; - nfapi_nr_dl_tti_request_t *DL_req = Sched_INFO->DL_req; - nfapi_nr_tx_data_request_t *TX_req = Sched_INFO->TX_req; - nfapi_nr_ul_tti_request_t *UL_tti_req = Sched_INFO->UL_tti_req; - nfapi_nr_ul_dci_request_t *UL_dci_req = Sched_INFO->UL_dci_req; + nfapi_nr_dl_tti_request_t *DL_req = &Sched_INFO->DL_req; + nfapi_nr_tx_data_request_t *TX_req = &Sched_INFO->TX_req; + nfapi_nr_ul_tti_request_t *UL_tti_req = &Sched_INFO->UL_tti_req; + nfapi_nr_ul_dci_request_t *UL_dci_req = &Sched_INFO->UL_dci_req; frame_t frame = Sched_INFO->frame; sub_frame_t slot = Sched_INFO->slot; @@ -169,6 +170,8 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO) msgTx->num_ul_pdcch = number_ul_dci_pdu; msgTx->slot = slot; msgTx->frame = frame; + /* store the sched_response_id for the TX thread to release it when done */ + msgTx->sched_response_id = Sched_INFO->sched_response_id; for (int i=0;idl_tti_request_body.dl_tti_pdu_list[i]; @@ -208,6 +211,11 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO) for (int i=0; iul_pdcch_pdu[i] = UL_dci_req->ul_dci_pdu_list[i]; + /* Both the current thread and the TX thread will access the sched_info + * at the same time, so increase its reference counter, so that it is + * released only when both threads are done with it. + */ + inc_ref_sched_response(Sched_INFO->sched_response_id); pushNotifiedFIFO(&gNB->L1_tx_filled,res); } @@ -250,5 +258,9 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO) if (number_dl_pdu>0) oai_nfapi_dl_tti_req(DL_req); } + + /* this thread is done with the sched_info, decrease the reference counter */ + deref_sched_response(Sched_INFO->sched_response_id); + stop_meas(&gNB->schedule_response_stats); } diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index 1439c9fd01..f075a4a621 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -83,7 +83,7 @@ typedef struct { - uint8_t decoded_output[64]; + uint8_t decoded_output[3]; // PBCH paylod not larger than 3B uint8_t xtra_byte; } fapiPbch_t; @@ -98,17 +98,16 @@ typedef struct { */ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data); -/*! \brief Scheduling for UE RX procedures in normal subframes. - @param ue Pointer to UE variables on which to act - @param proc Pointer to proc information - @param dlsch_parallel use multithreaded dlsch processing - @param phy_pdcch_config PDCCH Config for this slot - @param txFifo Result fifo if PDSCH is run in parallel -*/ -int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, +void send_slot_ind(notifiedFIFO_t *nf, int slot); + +void pbch_pdcch_processing(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data); +void pdsch_processing(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + nr_phy_data_t *phy_data); + int phy_procedures_slot_parallelization_nrUE_RX(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t abstraction_flag, uint8_t do_pdcch_flag, relaying_type_t r_type); void processSlotTX(void *arg); @@ -166,7 +165,8 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, NR_UE_DLSCH_t *dlsch1, uint16_t n_pdus, UE_nr_rxtx_proc_t *proc, - void *typeSpecific); + void *typeSpecific, + uint8_t *b); bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 255ecf17ca..64ec900b2a 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -544,8 +544,10 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config) { fapi_nr_config_request_t *nrUE_config = &PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->nrUE_config; - if(phy_config != NULL) + if(phy_config != NULL) { memcpy(nrUE_config,&phy_config->config_req,sizeof(fapi_nr_config_request_t)); + pushNotifiedFIFO(&PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->phy_config_ind, newNotifiedFIFO_elt(1,0,NULL,NULL)); + } return 0; } diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index f88b81ad52..664cddcfdf 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -118,10 +118,9 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, NR_UE_DLSCH_t *dlsch1, uint16_t n_pdus, UE_nr_rxtx_proc_t *proc, - void *typeSpecific){ - - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - + void *typeSpecific, + uint8_t *b) +{ if (n_pdus > 1){ LOG_E(PHY, "In %s: multiple number of DL PDUs not supported yet...\n", __FUNCTION__); } @@ -131,7 +130,7 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, if ((pdu_type != FAPI_NR_RX_PDU_TYPE_SSB) && dlsch0) { dl_harq0 = &ue->dl_harq_processes[0][dlsch0->dlsch_config.harq_process_nbr]; trace_NRpdu(DIRECTION_DOWNLINK, - dl_harq0->b, + b, dlsch0->dlsch_config.TBS / 8, WS_C_RNTI, dlsch0->rnti, @@ -147,24 +146,30 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, dl_harq0 = &ue->dl_harq_processes[0][dlsch0->dlsch_config.harq_process_nbr]; rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.harq_pid = dlsch0->dlsch_config.harq_process_nbr; rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.ack_nack = dl_harq0->ack; - rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu = dl_harq0->b; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu = b; rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu_length = dlsch0->dlsch_config.TBS / 8; } if(dlsch1) { AssertFatal(1==0,"Second codeword currently not supported\n"); } break; - case FAPI_NR_RX_PDU_TYPE_SSB: - rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.pdu=malloc(sizeof(((fapiPbch_t*)typeSpecific)->decoded_output)); - memcpy(rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.pdu, - ((fapiPbch_t*)typeSpecific)->decoded_output, - sizeof(((fapiPbch_t*)typeSpecific)->decoded_output)); - rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.additional_bits = ((fapiPbch_t*)typeSpecific)->xtra_byte; - rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_index = (frame_parms->ssb_index)&0x7; - rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_length = frame_parms->Lmax; - rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.cell_id = frame_parms->Nid_cell; - rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_start_subcarrier = frame_parms->ssb_start_subcarrier; - rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.rsrp_dBm = ue->measurements.ssb_rsrp_dBm[frame_parms->ssb_index]; + case FAPI_NR_RX_PDU_TYPE_SSB: { + fapi_nr_ssb_pdu_t *ssb_pdu = &rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu; + if(typeSpecific) { + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + fapiPbch_t *pbch = (fapiPbch_t *)typeSpecific; + memcpy(ssb_pdu->pdu, pbch->decoded_output, sizeof(pbch->decoded_output)); + ssb_pdu->additional_bits = pbch->xtra_byte; + ssb_pdu->ssb_index = (frame_parms->ssb_index)&0x7; + ssb_pdu->ssb_length = frame_parms->Lmax; + 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->decoded_pdu = true; + } + else + ssb_pdu->decoded_pdu = false; + } break; case FAPI_NR_CSIRS_IND: memcpy(&rx_ind->rx_indication_body[n_pdus - 1].csirs_measurements, @@ -382,7 +387,6 @@ static void nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue, proc, estimateSz, dl_ch_estimates, - ue->pbch_vars[gNB_id], &ue->frame_parms, (ue->frame_parms.ssb_index)&7, SISO, @@ -392,8 +396,6 @@ static void nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue, if (ret==0) { - ue->pbch_vars[gNB_id]->pdu_errors_conseq = 0; - #ifdef DEBUG_PHY_PROC uint16_t frame_tx; LOG_D(PHY,"[UE %d] frame %d, nr_slot_rx %d, Received PBCH (MIB): frame_tx %d. N_RB_DL %d\n", @@ -426,36 +428,12 @@ static void nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue, write_output("H10.m","h10",&(ue->common_vars.dl_ch_estimates[0][2][0]),((ue->frame_parms.Ncp==0)?7:6)*(ue->frame_parms.ofdm_symbol_size),1,1); write_output("rxsigF0.m","rxsF0", ue->common_vars.rxdataF[0],8*ue->frame_parms.ofdm_symbol_size,1,1); - write_output("PBCH_rxF0_ext.m","pbch0_ext",ue->pbch_vars[0]->rxdataF_ext[0],12*4*6,1,1); - write_output("PBCH_rxF0_comp.m","pbch0_comp",ue->pbch_vars[0]->rxdataF_comp[0],12*4*6,1,1); - write_output("PBCH_rxF_llr.m","pbch_llr",ue->pbch_vars[0]->llr,(ue->frame_parms.Ncp==0) ? 1920 : 1728,1,4); exit(-1); */ - ue->pbch_vars[gNB_id]->pdu_errors_conseq++; - ue->pbch_vars[gNB_id]->pdu_errors++; - - if (ue->pbch_vars[gNB_id]->pdu_errors_conseq>=100) { - if (get_softmodem_params()->non_stop) { - LOG_E(PHY,"More that 100 consecutive PBCH errors! Going back to Sync mode!\n"); - ue->lost_sync = 1; - } else { - LOG_E(PHY,"More that 100 consecutive PBCH errors! Exiting!\n"); - exit_fun("More that 100 consecutive PBCH errors! Exiting!\n"); - } - } } - if (frame_rx % 100 == 0) { - ue->pbch_vars[gNB_id]->pdu_errors_last = ue->pbch_vars[gNB_id]->pdu_errors; - } -#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] frame %d, slot %d, PBCH errors = %d, consecutive errors = %d!\n", - ue->Mod_id,frame_rx, nr_slot_rx, - ue->pbch_vars[gNB_id]->pdu_errors, - ue->pbch_vars[gNB_id]->pdu_errors_conseq); -#endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_OUT); } @@ -696,6 +674,15 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, return 0; } +void send_slot_ind(notifiedFIFO_t *nf, int slot) { + if (nf) { + notifiedFIFO_elt_t *newElt = newNotifiedFIFO_elt(sizeof(int), 0, NULL, NULL); + int *msgData = (int *) NotifiedFifoData(newElt); + *msgData = slot; + pushNotifiedFIFO(nf, newElt); + } +} + bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, NR_UE_DLSCH_t dlsch[2], @@ -716,7 +703,7 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, NR_DL_UE_HARQ_t *dl_harq1 = &ue->dl_harq_processes[1][harq_pid]; uint16_t dmrs_len = get_num_dmrs(dlsch[0].dlsch_config.dlDmrsSymbPos); nr_downlink_indication_t dl_indication; - fapi_nr_rx_indication_t *rx_ind = calloc(1, sizeof(*rx_ind)); + fapi_nr_rx_indication_t rx_ind = {0}; uint16_t number_pdus = 1; // params for UL time alignment procedure NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[gNB_id]; @@ -739,8 +726,12 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, LOG_D(PHY,"AbsSubframe %d.%d Start LDPC Decoder for CW1 [harq_pid %d] ? %d \n", frame_rx%1024, nr_slot_rx, harq_pid, is_cw1_active); // exit dlsch procedures as there are no active dlsch - if (is_cw0_active != ACTIVE && is_cw1_active != ACTIVE) + if (is_cw0_active != ACTIVE && is_cw1_active != ACTIVE) { + // don't wait anymore + const int ack_nack_slot = (proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) % ue->frame_parms.slots_per_frame; + send_slot_ind(ue->tx_resume_ind_fifo[ack_nack_slot], proc->nr_slot_rx); return false; + } // start ldpc decode for CW 0 dl_harq0->G = nr_get_G(dlsch[0].dlsch_config.number_rbs, @@ -762,6 +753,16 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, start_meas(&ue->dlsch_decoding_stats); + // create memory to store decoder output + int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated + int num_rb = dlsch[0].dlsch_config.number_rbs; + if (num_rb != 273) { + a_segments = a_segments*num_rb; + a_segments = (a_segments/273)+1; + } + uint32_t dlsch_bytes = a_segments*1056; // allocated bytes per segment + __attribute__ ((aligned(32))) uint8_t p_b[dlsch_bytes]; + ret = nr_dlsch_decoding(ue, proc, gNB_id, @@ -772,7 +773,9 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, frame_rx, nb_symb_sch, nr_slot_rx, - harq_pid); + harq_pid, + dlsch_bytes, + p_b); LOG_T(PHY,"dlsch decoding, ret = %d\n", ret); @@ -799,8 +802,8 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, break; } - nr_fill_dl_indication(&dl_indication, NULL, rx_ind, proc, ue, NULL); - nr_fill_rx_indication(rx_ind, ind_type, ue, &dlsch[0], NULL, number_pdus, proc, NULL); + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); + nr_fill_rx_indication(&rx_ind, ind_type, ue, &dlsch[0], NULL, number_pdus, proc, NULL, p_b); LOG_D(PHY, "In %s DL PDU length in bits: %d, in bytes: %d \n", __FUNCTION__, dlsch[0].dlsch_config.TBS, dlsch[0].dlsch_config.TBS / 8); @@ -840,7 +843,9 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, frame_rx, nb_symb_sch, nr_slot_rx, - harq_pid); + harq_pid, + dlsch_bytes, + p_b); LOG_T(PHY,"CW dlsch decoding, ret1 = %d\n", ret1); stop_meas(&ue->dlsch_decoding_stats); @@ -857,6 +862,13 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, ue->if_inst->dl_indication(&dl_indication, ul_time_alignment); } + // DLSCH decoding finished! don't wait anymore + const int ack_nack_slot = (proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) % ue->frame_parms.slots_per_frame; + send_slot_ind(ue->tx_resume_ind_fifo[ack_nack_slot], proc->nr_slot_rx); + + if (ue->phy_sim_dlsch_b) + memcpy(ue->phy_sim_dlsch_b, p_b, dlsch_bytes); + if (ue->mac_enabled == 1) { // TODO: move this from PHY to MAC layer! /* Time Alignment procedure @@ -989,8 +1001,7 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, return dec; } - -int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, +void pbch_pdcch_processing(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data) { @@ -1124,7 +1135,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, p += snprintf(p, end - p, "Harq round stats for Downlink: %d", ue->dl_stats[0]); for (int round = 1; round < 16 && (round < 3 || ue->dl_stats[round] != 0); ++round) p += snprintf(p, end - p,"/%d", ue->dl_stats[round]); - LOG_I(NR_PHY,"%s/0\n", output); + LOG_I(NR_PHY,"%s\n", output); LOG_I(NR_PHY,"============================================\n"); } @@ -1169,41 +1180,44 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, } dci_cnt = dci_cnt + nr_ue_pdcch_procedures(ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, phy_data, n_ss, rxdataF); } + LOG_D(PHY,"[UE %d] Frame %d, nr_slot_rx %d: found %d DCIs\n", ue->Mod_id, frame_rx, nr_slot_rx, dci_cnt); phy_pdcch_config->nb_search_space = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_OUT); +} + +void pdsch_processing(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + nr_phy_data_t *phy_data) { + + int frame_rx = proc->frame_rx; + int nr_slot_rx = proc->nr_slot_rx; + int gNB_id = proc->gNB_id; NR_UE_DLSCH_t *dlsch = &phy_data->dlsch[0]; - if (dci_cnt > 0) { - - LOG_D(PHY,"[UE %d] Frame %d, nr_slot_rx %d: found %d DCIs\n", ue->Mod_id, frame_rx, nr_slot_rx, dci_cnt); - - if (dlsch->active) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_IN); - uint16_t nb_symb_sch = dlsch[0].dlsch_config.number_symbols; - uint16_t start_symb_sch = dlsch[0].dlsch_config.start_symbol; - - LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx); - //to update from pdsch config - - for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){ - nr_slot_fep(ue, - proc, - m, //to be updated from higher layer - rxdataF); - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_OUT); - } - } else { - LOG_D(PHY,"[UE %d] Frame %d, nr_slot_rx %d: No DCIs found\n", ue->Mod_id, frame_rx, nr_slot_rx); - } - #endif //NR_PDCCH_SCHED - start_meas(&ue->generic_stat); // do procedures for C-RNTI int ret_pdsch = 0; + + const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP; + __attribute__ ((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz]; if (dlsch[0].active) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_IN); + uint16_t nb_symb_sch = dlsch[0].dlsch_config.number_symbols; + uint16_t start_symb_sch = dlsch[0].dlsch_config.start_symbol; + + LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx); + //to update from pdsch config + + for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){ + nr_slot_fep(ue, + proc, + m, //to be updated from higher layer + rxdataF); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_OUT); + uint8_t nb_re_dmrs; if (dlsch[0].dlsch_config.dmrsConfigType == NFAPI_NR_DMRS_TYPE1) { nb_re_dmrs = 6*dlsch[0].dlsch_config.n_dmrs_cdm_groups; @@ -1243,6 +1257,9 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, if (ret_pdsch >= 0) nr_ue_dlsch_procedures(ue, proc, dlsch, llr); + else + // don't wait anymore + send_slot_ind(ue->tx_resume_ind_fifo[(proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) % ue->frame_parms.slots_per_frame], proc->nr_slot_rx); stop_meas(&ue->dlsch_procedures_stat); if (cpumeas(CPUMEAS_GETSTATE)) { @@ -1333,7 +1350,6 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, LOG_D(PHY," ****** end RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, nr_slot_rx); UEscopeCopy(ue, commonRxdataF, rxdataF, sizeof(int32_t), ue->frame_parms.nb_antennas_rx, rxdataF_sz); - return (0); } diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index cdbe21465f..c98bc4ee04 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -81,6 +81,17 @@ void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {} NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { return (NULL); } nfapi_mode_t nfapi_getmode(void) { return NFAPI_MODE_UNKNOWN; } +void inc_ref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} +void deref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} + nrUE_params_t nrUE_params={0}; nrUE_params_t *get_nrUE_params(void) { @@ -542,9 +553,17 @@ int main(int argc, char **argv) vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING0, VCD_FUNCTION_IN); + int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated + int num_rb = dlsch0_ue->dlsch_config.number_rbs; + if (num_rb != 273) { + a_segments = a_segments*num_rb; + a_segments = (a_segments/273)+1; + } + uint32_t dlsch_bytes = a_segments*1056; // allocated bytes per segment + __attribute__ ((aligned(32))) uint8_t b[dlsch_bytes]; ret = nr_dlsch_decoding(UE, &proc, 0, channel_output_fixed, &UE->frame_parms, dlsch0_ue, harq_process, frame, nb_symb_sch, - slot,harq_pid); + slot,harq_pid,dlsch_bytes,b); vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING0, VCD_FUNCTION_OUT); @@ -555,7 +574,7 @@ int main(int argc, char **argv) errors_bit = 0; for (i = 0; i < TBS; i++) { - estimated_output_bit[i] = (harq_process->b[i / 8] & (1 << (i & 7))) >> (i & 7); + estimated_output_bit[i] = (b[i / 8] & (1 << (i & 7))) >> (i & 7); test_input_bit[i] = (test_input[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments if (estimated_output_bit[i] != test_input_bit[i]) { diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index b2c9ac5a33..5f9beb9ddc 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -328,7 +328,7 @@ int main(int argc, char **argv) //int frame_length_complex_samples_no_prefix; NR_DL_FRAME_PARMS *frame_parms; UE_nr_rxtx_proc_t UE_proc; - NR_Sched_Rsp_t Sched_INFO; + NR_Sched_Rsp_t *Sched_INFO; gNB_MAC_INST *gNB_mac; NR_UE_MAC_INST_t *UE_mac; int cyclic_prefix_type = NFAPI_CP_NORMAL; @@ -940,6 +940,13 @@ int main(int argc, char **argv) UE->phy_sim_pdsch_rxdataF_comp = calloc(sizeof(int32_t *) * frame_parms->nb_antennas_rx * g_nrOfLayers, rx_size); UE->phy_sim_pdsch_dl_ch_estimates = calloc(sizeof(int32_t *) * frame_parms->nb_antennas_rx * g_nrOfLayers, rx_size); UE->phy_sim_pdsch_dl_ch_estimates_ext = calloc(sizeof(int32_t *) * frame_parms->nb_antennas_rx * g_nrOfLayers, rx_size); + int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated + if (g_rbSize != 273) { + a_segments = a_segments*g_rbSize; + a_segments = (a_segments/273)+1; + } + uint32_t dlsch_bytes = a_segments*1056; // allocated bytes per segment + UE->phy_sim_dlsch_b = calloc(1, dlsch_bytes); for (SNR = snr0; SNR < snr1; SNR += .2) { @@ -994,28 +1001,33 @@ int main(int argc, char **argv) round = 0; UE_harq_process->DLround = round; UE_harq_process->first_rx = 1; - + + Sched_INFO = malloc(sizeof(*Sched_INFO)); + if (Sched_INFO == NULL) { + LOG_E(PHY, "out of memory\n"); + exit(1); + } + memset(Sched_INFO, 0, sizeof(*Sched_INFO)); + Sched_INFO->sched_response_id = -1; + while ((roundack==0)) { round_trials[round]++; - clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot); + clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req, &Sched_INFO->UL_dci_req); UE_info->UE_sched_ctrl.harq_processes[harq_pid].ndi = !(trial&1); UE_info->UE_sched_ctrl.harq_processes[harq_pid].round = round; - nr_schedule_ue_spec(0, frame, slot); - Sched_INFO.module_id = 0; - Sched_INFO.CC_id = 0; - Sched_INFO.frame = frame; - Sched_INFO.slot = slot; - Sched_INFO.DL_req = &gNB_mac->DL_req[0]; - Sched_INFO.UL_tti_req = gNB_mac->UL_tti_req_ahead[0]; - Sched_INFO.UL_dci_req = NULL; - Sched_INFO.TX_req = &gNB_mac->TX_req[0]; + nr_schedule_ue_spec(0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req); + Sched_INFO->module_id = 0; + Sched_INFO->CC_id = 0; + Sched_INFO->frame = frame; + Sched_INFO->slot = slot; + Sched_INFO->UL_dci_req.numPdus = 0; pushNotifiedFIFO(&gNB->L1_tx_free,msgL1Tx); - nr_schedule_response(&Sched_INFO); + nr_schedule_response(Sched_INFO); /* PTRS values for DLSIM calculations */ - nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[Sched_INFO.CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &Sched_INFO->DL_req.dl_tti_request_body; nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[1]; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; pdu_bit_map = pdsch_pdu_rel15->pduBitmap; @@ -1153,9 +1165,12 @@ int main(int argc, char **argv) nr_ue_dcireq(&dcireq); //to be replaced with function pointer later nr_ue_scheduled_response(&scheduled_response); - phy_procedures_nrUE_RX(UE, - &UE_proc, - &phy_data); + pbch_pdcch_processing(UE, + &UE_proc, + &phy_data); + pdsch_processing(UE, + &UE_proc, + &phy_data); //---------------------------------------------------------- //---------------------- count errors ---------------------- @@ -1198,7 +1213,7 @@ int main(int argc, char **argv) for (i = 0; i < TBS; i++) { - estimated_output_bit[i] = (UE_harq_process->b[i/8] & (1 << (i & 7))) >> (i & 7); + estimated_output_bit[i] = (UE->phy_sim_dlsch_b[i/8] & (1 << (i & 7))) >> (i & 7); test_input_bit[i] = (gNB_dlsch->harq_process.b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments if (estimated_output_bit[i] != test_input_bit[i]) { @@ -1347,6 +1362,7 @@ int main(int argc, char **argv) free(UE->phy_sim_pdsch_rxdataF_comp); free(UE->phy_sim_pdsch_dl_ch_estimates); free(UE->phy_sim_pdsch_dl_ch_estimates_ext); + free(UE->phy_sim_dlsch_b); if (output_fd) fclose(output_fd); diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index ee67e8d52e..f16f8fc5f1 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -67,6 +67,17 @@ openair0_config_t openair0_cfg[MAX_CARDS]; uint8_t const nr_rv_round_map[4] = {0, 2, 3, 1}; +void inc_ref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} +void deref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} + uint64_t get_softmodem_optmask(void) {return 0;} static softmodem_params_t softmodem_params; softmodem_params_t *get_softmodem_params(void) { @@ -96,7 +107,8 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, NR_UE_DLSCH_t *dlsch1, uint16_t n_pdus, UE_nr_rxtx_proc_t *proc, - void *typeSpecific ) {} + void *typeSpecific, + uint8_t *b) {} int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, @@ -793,8 +805,8 @@ int main(int argc, char **argv) fapiPbch_t result; ret = nr_rx_pbch(UE, &proc, - estimateSz, dl_ch_estimates, - UE->pbch_vars[0], + estimateSz, + dl_ch_estimates, frame_parms, ssb_index%8, SISO, @@ -813,7 +825,6 @@ int main(int argc, char **argv) for (i=0;i<3;i++){ payload_ret += (result.decoded_output[i] == ((msgDataTx.ssb[ssb_index].ssb_pdu.ssb_pdu_rel15.bchPayload>>(8*i)) & 0xff)); } - //printf("xtra byte gNB: 0x%02x UE: 0x%02x\n",gNB_xtra_byte, UE->pbch_vars[0]->xtra_byte); //printf("ret %d\n", payload_ret); if (payload_ret!=4) n_errors_payload++; diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 629b7316b0..aa441e4c61 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -86,6 +86,17 @@ softmodem_params_t *get_softmodem_params(void) {return 0;} instance_t DUuniqInstance=0; instance_t CUuniqInstance=0; +void inc_ref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} +void deref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} + int nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star) { return 0; diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index 01eec03c4d..a0631767ba 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -73,6 +73,17 @@ void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {} NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { return (NULL); } nfapi_mode_t nfapi_getmode(void) { return NFAPI_MODE_UNKNOWN; } +void inc_ref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} +void deref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} + nrUE_params_t nrUE_params={0}; nrUE_params_t *get_nrUE_params(void) { diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index 344f3f3310..69b12e78ee 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -80,6 +80,17 @@ PHY_VARS_NR_UE *PHY_vars_UE_g[1][1] = { { NULL } }; uint16_t n_rnti = 0x1234; openair0_config_t openair0_cfg[MAX_CARDS]; +void inc_ref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} +void deref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} + int nr_postDecode_sim(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) { ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req); NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 109b4faf20..d8ffdcc55e 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -759,10 +759,10 @@ int main(int argc, char **argv) NR_gNB_ULSCH_t *ulsch_gNB = &gNB->ulsch[UE_id]; // nfapi_nr_ul_config_ulsch_pdu *rel15_ul = &ulsch_gNB->harq_process->ulsch_pdu; - nfapi_nr_ul_tti_request_t *UL_tti_req = malloc(sizeof(*UL_tti_req)); NR_Sched_Rsp_t *Sched_INFO = malloc(sizeof(*Sched_INFO)); memset((void*)Sched_INFO,0,sizeof(*Sched_INFO)); - Sched_INFO->UL_tti_req=UL_tti_req; + nfapi_nr_ul_tti_request_t *UL_tti_req = &Sched_INFO->UL_tti_req; + Sched_INFO->sched_response_id = -1; nr_phy_data_tx_t phy_data = {0}; diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index bd08153aff..8dfc05952d 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -701,6 +701,9 @@ int nr_rrc_mac_config_req_ue(module_id_t module_id, RA_config_t *ra = &mac->ra; fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; + if (mac->dl_config_request == NULL) // for SIB1 reception + mac->dl_config_request = calloc(NR_MAX_SLOTS_PER_FRAME, sizeof(*mac->dl_config_request)); + // TODO do something FAPI-like P5 L1/L2 config interface in config_si, config_mib, etc. if(mibP != NULL){ @@ -726,9 +729,21 @@ int nr_rrc_mac_config_req_ue(module_id_t module_id, } } LOG_I(NR_MAC, "Initializing ul_config_request. num_slots_ul = %d\n", num_slots_ul); - mac->ul_config_request = (fapi_nr_ul_config_request_t *)calloc(num_slots_ul, sizeof(fapi_nr_ul_config_request_t)); + mac->ul_config_request = calloc(num_slots_ul, sizeof(*mac->ul_config_request)); for (int i=0; iul_config_request[i].mutex_ul_config), NULL); + + int num_slots_dl = nr_slots_per_frame[mac->mib->subCarrierSpacingCommon]; + if (cfg->cell_config.frame_duplex_type == TDD) { + num_slots_dl = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots; + if (mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols > 0) { + num_slots_dl++; + } + } + LOG_I(NR_MAC, "Initializing dl_config_request. num_slots_dl = %d\n", num_slots_dl); + mac->dl_config_request = realloc(mac->dl_config_request, num_slots_dl*sizeof(*mac->dl_config_request)); + memset(mac->dl_config_request, 0, num_slots_dl*sizeof(fapi_nr_dl_config_request_t)); + // Setup the SSB to Rach Occasionsif (cell_group_config->spCellConfig) { mapping according to the config build_ssb_to_ro_map(mac);//->scc, mac->phy_config.config_req.cell_config.frame_duplex_type); if (!get_softmodem_params()->emulate_l1) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index b1af5393a1..25063f3141 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -376,8 +376,9 @@ typedef struct { uint32_t ssb_index; /// SSB RSRP in dBm short ssb_rsrp_dBm; + int consecutive_bch_failures; -} NR_PHY_meas_t; +} NR_SSB_meas_t; /*!\brief Top level UE MAC structure */ typedef struct { @@ -441,7 +442,7 @@ typedef struct { int first_ul_tx[NR_MAX_HARQ_PROCESSES]; //// FAPI-like interface message fapi_nr_ul_config_request_t *ul_config_request; - fapi_nr_dl_config_request_t dl_config_request; + fapi_nr_dl_config_request_t *dl_config_request; /// Interface module instances nr_ue_if_module_t *if_module; @@ -465,9 +466,9 @@ typedef struct { uint16_t nr_band; uint8_t ssb_subcarrier_offset; - NR_PHY_meas_t phy_measurements; + NR_SSB_meas_t ssb_measurements; - dci_pdu_rel15_t def_dci_pdu_rel15[8]; + dci_pdu_rel15_t def_dci_pdu_rel15[NR_MAX_SLOTS_PER_FRAME][8]; // Defined for abstracted mode nr_downlink_indication_t dl_info; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 9776003e3f..c8eec75d85 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -190,6 +190,8 @@ int8_t nr_ue_process_csirs_measurements(module_id_t module_id, frame_t frame, in uint32_t get_ssb_frame(uint32_t test); +void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger, int frame, int slot); + bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *pucch, frame_t frame, @@ -441,9 +443,11 @@ static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, uint16_t rnti, int ss_type, uint64_t *dci_pdu, - dci_pdu_rel15_t *dci_pdu_rel15); + dci_pdu_rel15_t *dci_pdu_rel15, + int slot); fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int slot); +fapi_nr_dl_config_request_t *get_dl_config_request(NR_UE_MAC_INST_t *mac, int slot); void fill_ul_config(fapi_nr_ul_config_request_t *ul_config, frame_t frame_tx, int slot_tx, uint8_t pdu_type); diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 2babe56ec8..31c665524e 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -55,6 +55,7 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) { nr_ue_mac_inst->sib1_decoded = false; nr_ue_mac_inst->phy_config_request_sent = false; nr_ue_mac_inst->state = UE_NOT_SYNC; + memset(&nr_ue_mac_inst->ssb_measurements, 0, sizeof(nr_ue_mac_inst->ssb_measurements)); for (int j=0;jra; - int16_t pathloss = compute_nr_SSB_PL(mac, mac->phy_measurements.ssb_rsrp_dBm); + int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm); int16_t ra_preamble_rx_power = (int16_t)(ra->prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER - pathloss + 30); return min(nr_get_Pcmax(mod_id), ra_preamble_rx_power); @@ -674,7 +674,7 @@ void nr_get_prach_resources(module_id_t mod_id, } else { /* TODO: This controls the tx_power of UE and the ramping procedure of RA of UE. Later we can abstract this, perhaps in the proxy. But for the time being lets leave it as below. */ - int16_t dl_pathloss = !get_softmodem_params()->emulate_l1 ? compute_nr_SSB_PL(mac, mac->phy_measurements.ssb_rsrp_dBm) : 0; + int16_t dl_pathloss = !get_softmodem_params()->emulate_l1 ? compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm) : 0; ssb_rach_config(ra, prach_resources, nr_rach_ConfigCommon); ra_preambles_config(prach_resources, mac, dl_pathloss); LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-based random access procedure... \n", ra->ra_PreambleIndex); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index 45b6a56978..5aa4438af0 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -172,7 +172,7 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t rel15->dci_length_options[i] = nr_dci_size(current_DL_BWP, current_UL_BWP, mac->cg, - &mac->def_dci_pdu_rel15[dci_format], + &mac->def_dci_pdu_rel15[dl_config->slot][dci_format], dci_format, NR_RNTI_TC, coreset, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 3978d52711..9542e19514 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -238,6 +238,8 @@ int8_t nr_ue_decode_mib(module_id_t module_id, AssertFatal(mac->mib != NULL, "nr_ue_decode_mib() mac->mib == NULL\n"); + mac->ssb_measurements.consecutive_bch_failures = 0; // resetting decoding failures + uint16_t frame = (mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused); uint16_t frame_number_4lsb = 0; @@ -316,9 +318,6 @@ int8_t nr_ue_decode_mib(module_id_t module_id, mac->first_sync_frame = frame; } - mac->dl_config_request.sfn = frame; - mac->dl_config_request.slot = ssb_start_symbol/14; - if(get_softmodem_params()->phy_test) mac->state = UE_CONNECTED; else if(mac->state == UE_NOT_SYNC) @@ -419,15 +418,15 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p int nr_ue_process_dci_indication_pdu(module_id_t module_id,int cc_id, int gNB_index, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci) { NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - dci_pdu_rel15_t *def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[dci->dci_format]; + dci_pdu_rel15_t *def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[slot][dci->dci_format]; LOG_D(MAC,"Received dci indication (rnti %x,dci format %d,n_CCE %d,payloadSize %d,payload %llx)\n", dci->rnti,dci->dci_format,dci->n_CCE,dci->payloadSize,*(unsigned long long*)dci->payloadBits); - int8_t ret = nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, dci->ss_type, (uint64_t *)dci->payloadBits, def_dci_pdu_rel15); + int8_t ret = nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, dci->ss_type, (uint64_t *)dci->payloadBits, def_dci_pdu_rel15, slot); if ((ret&1) == 1) return -1; else if (ret == 2) { dci->dci_format = NR_UL_DCI_FORMAT_0_0; - def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[dci->dci_format]; + def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[slot][dci->dci_format]; } int8_t ret_proc = nr_ue_process_dci(module_id, cc_id, gNB_index, frame, slot, def_dci_pdu_rel15, dci); return ret_proc; @@ -445,7 +444,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr bool valid_ptrs_setup = 0; NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); RA_config_t *ra = &mac->ra; - fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; + fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, slot); uint8_t is_Msg3 = 0; NR_UE_DL_BWP_t *current_DL_BWP = &mac->current_DL_BWP; NR_UE_UL_BWP_t *current_UL_BWP = &mac->current_UL_BWP; @@ -541,6 +540,11 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr // - SECOND_DAI // - SRS_RESOURCE_IND + /* SRS_REQUEST */ + AssertFatal(dci->srs_request.nbits == 2, "If SUL is supported in the cell, there is an additional bit in SRS request field\n"); + if(dci->srs_request.val > 0) + nr_ue_aperiodic_srs_scheduling(mac, dci->srs_request.val, frame, slot); + // Schedule PUSCH tda_info = get_ul_tda_info(current_UL_BWP, coreset_type, dci_ind->ss_type, get_rnti_type(mac, rnti), dci->time_domain_assignment.val); if (tda_info.nrOfSymbols == 0) @@ -809,6 +813,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_0->accumulated_delta_PUCCH, dci->pucch_resource_indicator, 1+dci->pdsch_to_harq_feedback_timing_indicator.val); + + dlsch_config_pdu_1_0->k1_feedback = 1+dci->pdsch_to_harq_feedback_timing_indicator.val; LOG_D(MAC,"(nr_ue_procedures.c) pdu_type=%d\n\n",dl_config->dl_config_list[dl_config->number_pdus].pdu_type); @@ -1071,14 +1077,15 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_1->n_front_load_symb); /* TCI */ - if (mac->dl_config_request.dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.tci_present_in_dci == 1){ + if (dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.coreset.tci_present_in_dci == 1){ // 0 bit if higher layer parameter tci-PresentInDCI is not enabled // otherwise 3 bits as defined in Subclause 5.1.5 of [6, TS38.214] dlsch_config_pdu_1_1->tci_state = dci->transmission_configuration_indication.val; } /* SRS_REQUEST */ - // if SUL is supported in the cell, there is an additional bit in this field and the value of this bit represents table 7.1.1.1-1 TS 38.212 FIXME!!! - dlsch_config_pdu_1_1->srs_config.aperiodicSRS_ResourceTrigger = (dci->srs_request.val & 0x11); // as per Table 7.3.1.1.2-24 TS 38.212 + AssertFatal(dci->srs_request.nbits == 2, "If SUL is supported in the cell, there is an additional bit in SRS request field\n"); + if(dci->srs_request.val > 0 ) + nr_ue_aperiodic_srs_scheduling(mac, dci->srs_request.val, frame, slot); /* CBGTI */ dlsch_config_pdu_1_1->cbgti = dci->cbgti.val; /* CBGFI */ @@ -1106,6 +1113,10 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr LOG_D(MAC,"(nr_ue_procedures.c) pdu_type=%d\n\n",dl_config->dl_config_list[dl_config->number_pdus].pdu_type); dl_config->number_pdus = dl_config->number_pdus + 1; + + // send the ack/nack slot number to phy to indicate tx thread to wait for DLSCH decoding + dlsch_config_pdu_1_1->k1_feedback = feedback_ti; + /* TODO same calculation for MCS table as done in UL */ dlsch_config_pdu_1_1->mcs_table = (pdsch_Config->mcs_Table) ? (*pdsch_Config->mcs_Table + 1) : 0; dlsch_config_pdu_1_1->qamModOrder = nr_get_Qm_dl(dlsch_config_pdu_1_1->mcs, dlsch_config_pdu_1_1->mcs_table); @@ -1208,14 +1219,12 @@ void set_harq_status(NR_UE_MAC_INST_t *mac, // FIXME k0 != 0 currently not taken into consideration current_harq->dl_frame = frame; current_harq->dl_slot = slot; - if (get_softmodem_params()->emulate_l1) { - int scs = get_softmodem_params()->numerology; - int slots_per_frame = nr_slots_per_frame[scs]; - slot += data_toul_fb; - if (slot >= slots_per_frame) { - frame = (frame + 1) % 1024; - slot %= slots_per_frame; - } + int scs = get_softmodem_params()->numerology; + int slots_per_frame = nr_slots_per_frame[scs]; + slot += data_toul_fb; + if (slot >= slots_per_frame) { + frame = (frame + 1) % 1024; + slot %= slots_per_frame; } LOG_D(NR_PHY,"Setting harq_status for harq_id %d, dl %d.%d, sched ul %d.%d\n", @@ -1564,7 +1573,7 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac, return (PUCCH_POWER_DEFAULT); } - int16_t pathloss = compute_nr_SSB_PL(mac, mac->phy_measurements.ssb_rsrp_dBm); + int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm); int M_pucch_component = (10 * log10((double)(pow(2,scs) * nb_of_prbs))); int16_t pucch_power = P_O_PUCCH + M_pucch_component + pathloss + delta_F_PUCCH + DELTA_TF + G_b_f_c; @@ -1820,10 +1829,14 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, } number_harq_feedback++; - if (current_harq->ack_received) + if (current_harq->ack_received) { ack_data[code_word][dai_current - 1] = current_harq->ack; - else + current_harq->active = false; + current_harq->ack_received = false; + } else { + LOG_W(NR_MAC, "DLSCH ACK/NACK reporting initiated for harq pid %d before DLSCH decoding completed\n", dl_harq_pid); ack_data[code_word][dai_current - 1] = 0; + } dai[code_word][dai_current - 1] = dai_current; pucch->resource_indicator = current_harq->pucch_resource_indicator; @@ -1831,9 +1844,7 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, pucch->N_CCE = current_harq->N_CCE; pucch->delta_pucch = current_harq->delta_pucch; pucch->is_common = current_harq->is_common; - current_harq->active = false; - current_harq->ack_received = false; - LOG_D(PHY,"%4d.%2d Sent %d ack on harq pid %d\n", frame, slot, current_harq->ack, dl_harq_pid); + LOG_D(PHY,"%4d.%2d Sent %d ack on harq pid %d\n", frame, slot, current_harq->ack, dl_harq_pid); } } } @@ -2179,7 +2190,7 @@ uint8_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, } } AssertFatal(*SSB_resource.list.array[ssb_rsrp[0][0]] == mac->mib_ssb, "Couldn't find corresponding SSB in csi_SSB_ResourceList\n"); - ssb_rsrp[1][0] = mac->phy_measurements.ssb_rsrp_dBm; + ssb_rsrp[1][0] = mac->ssb_measurements.ssb_rsrp_dBm; uint8_t ssbi; @@ -2398,7 +2409,8 @@ static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, uint16_t rnti, int ss_type, uint64_t *dci_pdu, - dci_pdu_rel15_t *dci_pdu_rel15) + dci_pdu_rel15_t *dci_pdu_rel15, + int slot) { int pos = 0; @@ -2466,8 +2478,8 @@ static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, //switch to DCI_0_0 if (dci_pdu_rel15->format_indicator == 0) { - dci_pdu_rel15 = &mac->def_dci_pdu_rel15[NR_UL_DCI_FORMAT_0_0]; - return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, ss_type, dci_pdu, dci_pdu_rel15); + dci_pdu_rel15 = &mac->def_dci_pdu_rel15[slot][NR_UL_DCI_FORMAT_0_0]; + return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, ss_type, dci_pdu, dci_pdu_rel15, slot); } #ifdef DEBUG_EXTRACT_DCI LOG_D(MAC,"Format indicator %d (%d bits) N_RB_BWP %d => %d (0x%lx)\n",dci_pdu_rel15->format_indicator,1,N_RB,dci_size-pos,*dci_pdu); @@ -2657,13 +2669,10 @@ static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, //switch to DCI_0_0 if (dci_pdu_rel15->format_indicator == 0) { - dci_pdu_rel15 = &mac->def_dci_pdu_rel15[NR_UL_DCI_FORMAT_0_0]; - return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, ss_type, dci_pdu, dci_pdu_rel15); + dci_pdu_rel15 = &mac->def_dci_pdu_rel15[slot][NR_UL_DCI_FORMAT_0_0]; + return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, ss_type, dci_pdu, dci_pdu_rel15, slot); } - if (dci_pdu_rel15->format_indicator == 0) - return 1; // discard dci, format indicator not corresponding to dci_format - // Freq domain assignment 0-16 bit fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)); pos+=fsize; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index b0d181f3da..a3f4d06b1c 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -112,11 +112,8 @@ fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int sl NR_TDD_UL_DL_ConfigCommon_t *tdd_config = mac->scc==NULL ? mac->scc_SIB->tdd_UL_DL_ConfigurationCommon : mac->scc->tdd_UL_DL_ConfigurationCommon; - //Check if request to access ul_config is for a UL slot - if (is_nr_UL_slot(tdd_config, slot, mac->frame_type) == 0) { - LOG_W(NR_MAC, "Slot %d is not a UL slot. %s called for wrong slot!!!\n", slot, __FUNCTION__); - return NULL; - } + //Check if requested on the right slot + AssertFatal(is_nr_UL_slot(tdd_config, slot, mac->frame_type) != 0, "%s called at wrong slot %d\n", __func__, slot); // Calculate the index of the UL slot in mac->ul_config_request list. This is // based on the TDD pattern (slot configuration period) and number of UL+mixed @@ -127,16 +124,57 @@ fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int sl const int num_slots_ul = tdd_config ? (tdd_config->pattern1.nrofUplinkSlots + (tdd_config->pattern1.nrofUplinkSymbols != 0)) : n; int index = slot % num_slots_ul; - LOG_D(NR_MAC, "In %s slots per %s: %d, num_slots_ul %d, index %d\n", + LOG_D(NR_MAC, "In %s slots per %s: %d, num_slots %d, index %d\n", __FUNCTION__, tdd_config ? "TDD" : "FDD", num_slots_per_tdd, num_slots_ul, index); - if(!mac->ul_config_request) + if (mac->ul_config_request) return &mac->ul_config_request[index]; + else { + LOG_E(NR_MAC, "mac->ul_config_request not set\n"); return NULL; - return &mac->ul_config_request[index]; + } +} + +/* + * This function returns the DL config corresponding to a given DL slot + * from MAC instance . + */ +fapi_nr_dl_config_request_t *get_dl_config_request(NR_UE_MAC_INST_t *mac, int slot) +{ + int index; + if (!mac->scc && !mac->scc_SIB) + index = 0; + else { + NR_TDD_UL_DL_ConfigCommon_t *tdd_config = mac->scc==NULL ? mac->scc_SIB->tdd_UL_DL_ConfigurationCommon : mac->scc->tdd_UL_DL_ConfigurationCommon; + + //Check if requested on the right slot + AssertFatal(is_nr_DL_slot(tdd_config, slot) != 0, "%s called at wrong slot %d\n", __func__, slot); + + // Calculate the index of the DL slot in mac->ul_config_request list. This is + // based on the TDD pattern (slot configuration period) and number of DL+mixed + // slots in the period. TS 38.213 Sec 11.1 + int mu = mac->current_UL_BWP.scs; + const int n = nr_slots_per_frame[mu]; + const int num_slots_per_tdd = tdd_config ? (n >> (7 - tdd_config->pattern1.dl_UL_TransmissionPeriodicity)) : n; + const int num_slots_dl = tdd_config ? (tdd_config->pattern1.nrofDownlinkSlots + (tdd_config->pattern1.nrofDownlinkSymbols != 0)) : n; + + index = slot % num_slots_dl; + LOG_D(NR_MAC, "In %s slots per %s: %d, num_slots %d, index %d\n", + __FUNCTION__, + tdd_config ? "TDD" : "FDD", + num_slots_per_tdd, + num_slots_dl, + index); + } + + if (mac->dl_config_request) return &mac->dl_config_request[index]; + else { + LOG_E(NR_MAC, "mac->dl_config_request not set\n"); + return NULL; + } } void ul_layers_config(NR_UE_MAC_INST_t *mac, nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, dci_pdu_rel15_t *dci, nr_dci_format_t dci_format) @@ -763,6 +801,140 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, } +void configure_srs_pdu(NR_UE_MAC_INST_t *mac, + NR_SRS_Resource_t *srs_resource, + fapi_nr_ul_config_srs_pdu *srs_config_pdu, + int period, int offset) +{ + NR_UE_UL_BWP_t *current_UL_BWP = &mac->current_UL_BWP; + + srs_config_pdu->rnti = mac->crnti; + srs_config_pdu->handle = 0; + srs_config_pdu->bwp_size = current_UL_BWP->BWPSize; + srs_config_pdu->bwp_start = current_UL_BWP->BWPStart; + srs_config_pdu->subcarrier_spacing = current_UL_BWP->scs; + srs_config_pdu->cyclic_prefix = 0; + srs_config_pdu->num_ant_ports = srs_resource->nrofSRS_Ports; + srs_config_pdu->num_symbols = srs_resource->resourceMapping.nrofSymbols; + srs_config_pdu->num_repetitions = srs_resource->resourceMapping.repetitionFactor; + srs_config_pdu->time_start_position = srs_resource->resourceMapping.startPosition; + srs_config_pdu->config_index = srs_resource->freqHopping.c_SRS; + srs_config_pdu->sequence_id = srs_resource->sequenceId; + srs_config_pdu->bandwidth_index = srs_resource->freqHopping.b_SRS; + srs_config_pdu->comb_size = srs_resource->transmissionComb.present - 1; + + switch(srs_resource->transmissionComb.present) { + case NR_SRS_Resource__transmissionComb_PR_n2: + srs_config_pdu->comb_offset = srs_resource->transmissionComb.choice.n2->combOffset_n2; + srs_config_pdu->cyclic_shift = srs_resource->transmissionComb.choice.n2->cyclicShift_n2; + break; + case NR_SRS_Resource__transmissionComb_PR_n4: + srs_config_pdu->comb_offset = srs_resource->transmissionComb.choice.n4->combOffset_n4; + srs_config_pdu->cyclic_shift = srs_resource->transmissionComb.choice.n4->cyclicShift_n4; + break; + default: + LOG_W(NR_MAC, "Invalid or not implemented comb_size!\n"); + } + + srs_config_pdu->frequency_position = srs_resource->freqDomainPosition; + srs_config_pdu->frequency_shift = srs_resource->freqDomainShift; + srs_config_pdu->frequency_hopping = srs_resource->freqHopping.b_hop; + srs_config_pdu->group_or_sequence_hopping = srs_resource->groupOrSequenceHopping; + srs_config_pdu->resource_type = srs_resource->resourceType.present - 1; + if(srs_config_pdu->resource_type > 0) { // not aperiodic + srs_config_pdu->t_srs = period; + srs_config_pdu->t_offset = offset; + } + +#ifdef SRS_DEBUG + LOG_I(NR_MAC,"Frame = %i, slot = %i\n", frame, slot); + LOG_I(NR_MAC,"srs_config_pdu->rnti = 0x%04x\n", srs_config_pdu->rnti); + LOG_I(NR_MAC,"srs_config_pdu->handle = %u\n", srs_config_pdu->handle); + LOG_I(NR_MAC,"srs_config_pdu->bwp_size = %u\n", srs_config_pdu->bwp_size); + LOG_I(NR_MAC,"srs_config_pdu->bwp_start = %u\n", srs_config_pdu->bwp_start); + LOG_I(NR_MAC,"srs_config_pdu->subcarrier_spacing = %u\n", srs_config_pdu->subcarrier_spacing); + LOG_I(NR_MAC,"srs_config_pdu->cyclic_prefix = %u (0: Normal; 1: Extended)\n", srs_config_pdu->cyclic_prefix); + LOG_I(NR_MAC,"srs_config_pdu->num_ant_ports = %u (0 = 1 port, 1 = 2 ports, 2 = 4 ports)\n", srs_config_pdu->num_ant_ports); + LOG_I(NR_MAC,"srs_config_pdu->num_symbols = %u (0 = 1 symbol, 1 = 2 symbols, 2 = 4 symbols)\n", srs_config_pdu->num_symbols); + LOG_I(NR_MAC,"srs_config_pdu->num_repetitions = %u (0 = 1, 1 = 2, 2 = 4)\n", srs_config_pdu->num_repetitions); + LOG_I(NR_MAC,"srs_config_pdu->time_start_position = %u\n", srs_config_pdu->time_start_position); + LOG_I(NR_MAC,"srs_config_pdu->config_index = %u\n", srs_config_pdu->config_index); + LOG_I(NR_MAC,"srs_config_pdu->sequence_id = %u\n", srs_config_pdu->sequence_id); + LOG_I(NR_MAC,"srs_config_pdu->bandwidth_index = %u\n", srs_config_pdu->bandwidth_index); + LOG_I(NR_MAC,"srs_config_pdu->comb_size = %u (0 = comb size 2, 1 = comb size 4, 2 = comb size 8)\n", srs_config_pdu->comb_size); + LOG_I(NR_MAC,"srs_config_pdu->comb_offset = %u\n", srs_config_pdu->comb_offset); + LOG_I(NR_MAC,"srs_config_pdu->cyclic_shift = %u\n", srs_config_pdu->cyclic_shift); + LOG_I(NR_MAC,"srs_config_pdu->frequency_position = %u\n", srs_config_pdu->frequency_position); + LOG_I(NR_MAC,"srs_config_pdu->frequency_shift = %u\n", srs_config_pdu->frequency_shift); + LOG_I(NR_MAC,"srs_config_pdu->frequency_hopping = %u\n", srs_config_pdu->frequency_hopping); + LOG_I(NR_MAC,"srs_config_pdu->group_or_sequence_hopping = %u (0 = No hopping, 1 = Group hopping groupOrSequenceHopping, 2 = Sequence hopping)\n", srs_config_pdu->group_or_sequence_hopping); + LOG_I(NR_MAC,"srs_config_pdu->resource_type = %u (0: aperiodic, 1: semi-persistent, 2: periodic)\n", srs_config_pdu->resource_type); + LOG_I(NR_MAC,"srs_config_pdu->t_srs = %u\n", srs_config_pdu->t_srs); + LOG_I(NR_MAC,"srs_config_pdu->t_offset = %u\n", srs_config_pdu->t_offset); +#endif +} + +// Aperiodic SRS scheduling +void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger, int frame, int slot) +{ + NR_UE_UL_BWP_t *current_UL_BWP = &mac->current_UL_BWP; + NR_SRS_Config_t *srs_config = current_UL_BWP->srs_Config; + + if (!srs_config) { + LOG_E(NR_MAC, "DCI is triggering aperiodic SRS but there is no SRS configuration\n"); + return; + } + + int slot_offset = 0; + NR_SRS_Resource_t *srs_resource = NULL; + for(int rs = 0; rs < srs_config->srs_ResourceSetToAddModList->list.count; rs++) { + + // Find aperiodic resource set + NR_SRS_ResourceSet_t *srs_resource_set = srs_config->srs_ResourceSetToAddModList->list.array[rs]; + if(srs_resource_set->resourceType.present != NR_SRS_ResourceSet__resourceType_PR_aperiodic) + continue; + // the resource trigger need to match the DCI one + if(srs_resource_set->resourceType.choice.aperiodic->aperiodicSRS_ResourceTrigger != resource_trigger) + continue; + // if slotOffset is null -> offset = 0 + if(srs_resource_set->resourceType.choice.aperiodic->slotOffset) + slot_offset = *srs_resource_set->resourceType.choice.aperiodic->slotOffset; + + // Find the corresponding srs resource + for(int r1 = 0; r1 < srs_resource_set->srs_ResourceIdList->list.count; r1++) { + for (int r2 = 0; r2 < srs_config->srs_ResourceToAddModList->list.count; r2++) { + if ((*srs_resource_set->srs_ResourceIdList->list.array[r1] == srs_config->srs_ResourceToAddModList->list.array[r2]->srs_ResourceId) && + (srs_config->srs_ResourceToAddModList->list.array[r2]->resourceType.present == NR_SRS_Resource__resourceType_PR_aperiodic)) { + srs_resource = srs_config->srs_ResourceToAddModList->list.array[r2]; + break; + } + } + } + } + + if(srs_resource == NULL) { + LOG_E(NR_MAC, "Couldn't find SRS aperiodic resource with trigger %ld\n", resource_trigger); + return; + } + + AssertFatal(slot_offset >= DURATION_RX_TO_TX,"Slot offset between DCI and aperiodic SRS (%d) cannot be less than DURATION_RX_TO_TX (%d)\n", + slot_offset, DURATION_RX_TO_TX); + int n_slots_frame = nr_slots_per_frame[current_UL_BWP->scs]; + int sched_slot = (slot + slot_offset) % n_slots_frame; + NR_TDD_UL_DL_ConfigCommon_t *tdd_config = mac->scc==NULL ? mac->scc_SIB->tdd_UL_DL_ConfigurationCommon : mac->scc->tdd_UL_DL_ConfigurationCommon; + if (!is_nr_UL_slot(tdd_config, sched_slot, mac->frame_type)) { + LOG_E(NR_MAC, "Slot for scheduling aperiodic SRS %d is not an UL slot\n", sched_slot); + return; + } + int sched_frame = frame + (slot + slot_offset >= n_slots_frame) % 1024; + + fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, sched_slot); + fapi_nr_ul_config_srs_pdu *srs_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].srs_config_pdu; + configure_srs_pdu(mac, srs_resource, srs_config_pdu, 0, 0); + fill_ul_config(ul_config, sched_frame, sched_slot, FAPI_NR_UL_CONFIG_TYPE_SRS); +} + + // Periodic SRS scheduling bool nr_ue_periodic_srs_scheduling(module_id_t mod_id, frame_t frame, slot_t slot) { @@ -812,68 +984,7 @@ bool nr_ue_periodic_srs_scheduling(module_id_t mod_id, frame_t frame, slot_t slo fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slot); fapi_nr_ul_config_srs_pdu *srs_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].srs_config_pdu; - srs_config_pdu->rnti = mac->crnti; - srs_config_pdu->handle = 0; - srs_config_pdu->bwp_size = current_UL_BWP->BWPSize; - srs_config_pdu->bwp_start = current_UL_BWP->BWPStart; - srs_config_pdu->subcarrier_spacing = current_UL_BWP->scs; - srs_config_pdu->cyclic_prefix = 0; - srs_config_pdu->num_ant_ports = srs_resource->nrofSRS_Ports; - srs_config_pdu->num_symbols = srs_resource->resourceMapping.nrofSymbols; - srs_config_pdu->num_repetitions = srs_resource->resourceMapping.repetitionFactor; - srs_config_pdu->time_start_position = srs_resource->resourceMapping.startPosition; - srs_config_pdu->config_index = srs_resource->freqHopping.c_SRS; - srs_config_pdu->sequence_id = srs_resource->sequenceId; - srs_config_pdu->bandwidth_index = srs_resource->freqHopping.b_SRS; - srs_config_pdu->comb_size = srs_resource->transmissionComb.present - 1; - - switch(srs_resource->transmissionComb.present) { - case NR_SRS_Resource__transmissionComb_PR_n2: - srs_config_pdu->comb_offset = srs_resource->transmissionComb.choice.n2->combOffset_n2; - srs_config_pdu->cyclic_shift = srs_resource->transmissionComb.choice.n2->cyclicShift_n2; - break; - case NR_SRS_Resource__transmissionComb_PR_n4: - srs_config_pdu->comb_offset = srs_resource->transmissionComb.choice.n4->combOffset_n4; - srs_config_pdu->cyclic_shift = srs_resource->transmissionComb.choice.n4->cyclicShift_n4; - break; - default: - LOG_W(NR_MAC, "Invalid or not implemented comb_size!\n"); - } - - srs_config_pdu->frequency_position = srs_resource->freqDomainPosition; - srs_config_pdu->frequency_shift = srs_resource->freqDomainShift; - srs_config_pdu->frequency_hopping = srs_resource->freqHopping.b_hop; - srs_config_pdu->group_or_sequence_hopping = srs_resource->groupOrSequenceHopping; - srs_config_pdu->resource_type = srs_resource->resourceType.present - 1; - srs_config_pdu->t_srs = period; - srs_config_pdu->t_offset = offset; - -#ifdef SRS_DEBUG - LOG_I(NR_MAC,"Frame = %i, slot = %i\n", frame, slot); - LOG_I(NR_MAC,"srs_config_pdu->rnti = 0x%04x\n", srs_config_pdu->rnti); - LOG_I(NR_MAC,"srs_config_pdu->handle = %u\n", srs_config_pdu->handle); - LOG_I(NR_MAC,"srs_config_pdu->bwp_size = %u\n", srs_config_pdu->bwp_size); - LOG_I(NR_MAC,"srs_config_pdu->bwp_start = %u\n", srs_config_pdu->bwp_start); - LOG_I(NR_MAC,"srs_config_pdu->subcarrier_spacing = %u\n", srs_config_pdu->subcarrier_spacing); - LOG_I(NR_MAC,"srs_config_pdu->cyclic_prefix = %u (0: Normal; 1: Extended)\n", srs_config_pdu->cyclic_prefix); - LOG_I(NR_MAC,"srs_config_pdu->num_ant_ports = %u (0 = 1 port, 1 = 2 ports, 2 = 4 ports)\n", srs_config_pdu->num_ant_ports); - LOG_I(NR_MAC,"srs_config_pdu->num_symbols = %u (0 = 1 symbol, 1 = 2 symbols, 2 = 4 symbols)\n", srs_config_pdu->num_symbols); - LOG_I(NR_MAC,"srs_config_pdu->num_repetitions = %u (0 = 1, 1 = 2, 2 = 4)\n", srs_config_pdu->num_repetitions); - LOG_I(NR_MAC,"srs_config_pdu->time_start_position = %u\n", srs_config_pdu->time_start_position); - LOG_I(NR_MAC,"srs_config_pdu->config_index = %u\n", srs_config_pdu->config_index); - LOG_I(NR_MAC,"srs_config_pdu->sequence_id = %u\n", srs_config_pdu->sequence_id); - LOG_I(NR_MAC,"srs_config_pdu->bandwidth_index = %u\n", srs_config_pdu->bandwidth_index); - LOG_I(NR_MAC,"srs_config_pdu->comb_size = %u (0 = comb size 2, 1 = comb size 4, 2 = comb size 8)\n", srs_config_pdu->comb_size); - LOG_I(NR_MAC,"srs_config_pdu->comb_offset = %u\n", srs_config_pdu->comb_offset); - LOG_I(NR_MAC,"srs_config_pdu->cyclic_shift = %u\n", srs_config_pdu->cyclic_shift); - LOG_I(NR_MAC,"srs_config_pdu->frequency_position = %u\n", srs_config_pdu->frequency_position); - LOG_I(NR_MAC,"srs_config_pdu->frequency_shift = %u\n", srs_config_pdu->frequency_shift); - LOG_I(NR_MAC,"srs_config_pdu->frequency_hopping = %u\n", srs_config_pdu->frequency_hopping); - LOG_I(NR_MAC,"srs_config_pdu->group_or_sequence_hopping = %u (0 = No hopping, 1 = Group hopping groupOrSequenceHopping, 2 = Sequence hopping)\n", srs_config_pdu->group_or_sequence_hopping); - LOG_I(NR_MAC,"srs_config_pdu->resource_type = %u (0: aperiodic, 1: semi-persistent, 2: periodic)\n", srs_config_pdu->resource_type); - LOG_I(NR_MAC,"srs_config_pdu->t_srs = %u\n", srs_config_pdu->t_srs); - LOG_I(NR_MAC,"srs_config_pdu->t_offset = %u\n", srs_config_pdu->t_offset); -#endif + configure_srs_pdu(mac, srs_resource, srs_config_pdu, period, offset); fill_ul_config(ul_config, frame, slot, FAPI_NR_UL_CONFIG_TYPE_SRS); srs_scheduled = true; @@ -895,7 +1006,9 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info) slot_t rx_slot = dl_info->slot; NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; + fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, rx_slot); + dl_config->sfn = rx_frame; + dl_config->slot = rx_slot; nr_scheduled_response_t scheduled_response; nr_dcireq_t dcireq; @@ -909,11 +1022,11 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info) dcireq.slot = rx_slot; dcireq.dl_config_req.number_pdus = 0; nr_ue_dcireq(&dcireq); //to be replaced with function pointer later - mac->dl_config_request = dcireq.dl_config_req; + *dl_config = dcireq.dl_config_req; nr_schedule_csirs_reception(mac, rx_frame, rx_slot); nr_schedule_csi_for_im(mac, rx_frame, rx_slot); - dcireq.dl_config_req = mac->dl_config_request; + dcireq.dl_config_req = *dl_config; fill_scheduled_response(&scheduled_response, &dcireq.dl_config_req, NULL, NULL, mod_id, cc_id, rx_frame, rx_slot, dl_info->phy_data); if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) { @@ -2177,7 +2290,7 @@ void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot) { if (csi_measconfig->csi_IM_ResourceToAddModList == NULL) return; - fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; + fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, slot); NR_CSI_IM_Resource_t *imcsi; int period, offset; @@ -2231,7 +2344,7 @@ void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot) { if (csi_measconfig->nzp_CSI_RS_ResourceToAddModList == NULL) return; - fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; + fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, slot); NR_NZP_CSI_RS_Resource_t *nzpcsi; int period, offset; NR_UE_DL_BWP_t *current_DL_BWP = &mac->current_DL_BWP; @@ -2553,9 +2666,6 @@ void nr_ue_sib1_scheduler(module_id_t module_idP, NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); nr_scheduled_response_t scheduled_response; - int frame_s,slot_s; - fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15; uint8_t scs_ssb = get_softmodem_params()->numerology; uint16_t ssb_offset_point_a = (ssb_start_subcarrier - ssb_subcarrier_offset)/12; @@ -2573,17 +2683,7 @@ void nr_ue_sib1_scheduler(module_id_t module_idP, 1, // If the UE is not configured with a periodicity, the UE assumes a periodicity of a half frame ssb_offset_point_a); - if(mac->search_space_zero == NULL) mac->search_space_zero=calloc(1,sizeof(*mac->search_space_zero)); - if(mac->coreset0 == NULL) mac->coreset0 = calloc(1,sizeof(*mac->coreset0)); - - fill_coresetZero(mac->coreset0, &mac->type0_PDCCH_CSS_config); - fill_searchSpaceZero(mac->search_space_zero, &mac->type0_PDCCH_CSS_config); - rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15; - rel15->num_dci_options = 1; - rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0; - config_dci_pdu(mac, rel15, dl_config, NR_RNTI_SI, -1); - fill_dci_search_candidates(mac->search_space_zero, rel15, -1, -1); - + int frame_s,slot_s; if(mac->type0_PDCCH_CSS_config.type0_pdcch_ss_mux_pattern == 1){ // same frame as ssb if ((mac->type0_PDCCH_CSS_config.frame & 0x1) == mac->type0_PDCCH_CSS_config.sfn_c) @@ -2596,6 +2696,20 @@ void nr_ue_sib1_scheduler(module_id_t module_idP, frame_s = 0; // same frame as ssb slot_s = mac->type0_PDCCH_CSS_config.n_c; } + fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request[0]; // Take the first dl_config_request for SIB1 + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15; + + if(mac->search_space_zero == NULL) mac->search_space_zero=calloc(1,sizeof(*mac->search_space_zero)); + if(mac->coreset0 == NULL) mac->coreset0 = calloc(1,sizeof(*mac->coreset0)); + + fill_coresetZero(mac->coreset0, &mac->type0_PDCCH_CSS_config); + fill_searchSpaceZero(mac->search_space_zero, &mac->type0_PDCCH_CSS_config); + rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15; + rel15->num_dci_options = 1; + rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0; + config_dci_pdu(mac, rel15, dl_config, NR_RNTI_SI, -1); + fill_dci_search_candidates(mac->search_space_zero, rel15, -1, -1); + LOG_D(MAC,"Calling fill_scheduled_response, type0_pdcch, num_pdus %d\n",dl_config->number_pdus); fill_scheduled_response(&scheduled_response, dl_config, NULL, NULL, module_idP, cc_id, frame_s, slot_s, phy_data); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 41a2153cf8..c4ed4e2d2a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -56,10 +56,13 @@ const uint8_t nr_rv_round_map[4] = { 0, 2, 3, 1 }; uint16_t nr_pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 }; -void clear_nr_nfapi_information(gNB_MAC_INST * gNB, +void clear_nr_nfapi_information(gNB_MAC_INST *gNB, int CC_idP, frame_t frameP, - sub_frame_t slotP) + sub_frame_t slotP, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req, + nfapi_nr_ul_dci_request_t *UL_dci_req) { NR_ServingCellConfigCommon_t *scc = gNB->common_channels->ServingCellConfigCommon; @@ -67,10 +70,7 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, UL_tti_req_ahead_initialization(gNB, scc, num_slots, CC_idP, frameP, slotP, *scc->ssbSubcarrierSpacing); - nfapi_nr_dl_tti_request_t *DL_req = &gNB->DL_req[0]; nfapi_nr_dl_tti_pdcch_pdu_rel15_t **pdcch = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t **)gNB->pdcch_pdu_idx[CC_idP]; - nfapi_nr_ul_dci_request_t *UL_dci_req = &gNB->UL_dci_req[0]; - nfapi_nr_tx_data_request_t *TX_req = &gNB->TX_req[0]; gNB->pdu_index[CC_idP] = 0; @@ -96,23 +96,53 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, future_ul_tti_req->n_ulcch = 0; future_ul_tti_req->n_group = 0; - /* UL_tti_req is a simple pointer into the current UL_tti_req_ahead, i.e., - * it walks over UL_tti_req_ahead in a circular fashion */ - const int current_index = ul_buffer_index(frameP, slotP, *scc->ssbSubcarrierSpacing, gNB->UL_tti_req_ahead_size); - gNB->UL_tti_req[CC_idP] = &gNB->UL_tti_req_ahead[CC_idP][current_index]; TX_req[CC_idP].Number_of_PDUs = 0; - } bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) { return (bitmap >> (slot % 64)) & 0x01; } -void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, - frame_t frame, - sub_frame_t slot) +/* the structure nfapi_nr_ul_tti_request_t is very big, let's copy only what is necessary */ +static void copy_ul_tti_req(nfapi_nr_ul_tti_request_t *to, nfapi_nr_ul_tti_request_t *from) { + int i; + to->header = from->header; + to->SFN = from->SFN; + to->Slot = from->Slot; + to->n_pdus = from->n_pdus; + to->rach_present = from->rach_present; + to->n_ulsch = from->n_ulsch; + to->n_ulcch = from->n_ulcch; + to->n_group = from->n_group; + + for (i = 0; i < from->n_pdus; i++) { + to->pdus_list[i].pdu_type = from->pdus_list[i].pdu_type; + to->pdus_list[i].pdu_size = from->pdus_list[i].pdu_size; + + switch (from->pdus_list[i].pdu_type) { + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: + to->pdus_list[i].prach_pdu = from->pdus_list[i].prach_pdu; + break; + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + to->pdus_list[i].pusch_pdu = from->pdus_list[i].pusch_pdu; + break; + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: + to->pdus_list[i].pucch_pdu = from->pdus_list[i].pucch_pdu; + break; + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: + to->pdus_list[i].srs_pdu = from->pdus_list[i].srs_pdu; + break; + } + } + + for (i = 0; i < from->n_group; i++) + to->groups_list[i] = from->groups_list[i]; +} + +void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_t slot, NR_Sched_Rsp_t *sched_info) +{ protocol_ctxt_t ctxt = {0}; PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frame, slot,module_idP); @@ -157,8 +187,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL; memcpy(&vrb_map_UL[prev_slot % size * MAX_BWP_SIZE], &gNB->ulprbbl, sizeof(uint16_t) * MAX_BWP_SIZE); - clear_nr_nfapi_information(gNB, CC_id, frame, slot); - + clear_nr_nfapi_information(gNB, CC_id, frame, slot, &sched_info->DL_req, &sched_info->TX_req, &sched_info->UL_dci_req); } if ((slot == 0) && (frame & 127) == 0) { @@ -172,12 +201,11 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, schedule_nr_bwp_switch(module_idP, frame, slot); // This schedules MIB - schedule_nr_mib(module_idP, frame, slot); + schedule_nr_mib(module_idP, frame, slot, &sched_info->DL_req); // This schedules SIB1 if (get_softmodem_params()->sa == 1) - schedule_nr_sib1(module_idP, frame, slot); - + schedule_nr_sib1(module_idP, frame, slot, &sched_info->DL_req, &sched_info->TX_req); // This schedule PRACH if we are not in phy_test mode if (get_softmodem_params()->phy_test == 0) { @@ -194,7 +222,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, } // Schedule CSI-RS transmission - nr_csirs_scheduling(module_idP, frame, slot, nr_slots_per_frame[*scc->ssbSubcarrierSpacing]); + nr_csirs_scheduling(module_idP, frame, slot, nr_slots_per_frame[*scc->ssbSubcarrierSpacing], &sched_info->DL_req); // Schedule CSI measurement reporting nr_csi_meas_reporting(module_idP, frame, slot); @@ -204,22 +232,29 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // This schedule RA procedure if not in phy_test mode // Otherwise consider 5G already connected if (get_softmodem_params()->phy_test == 0) { - nr_schedule_RA(module_idP, frame, slot); + nr_schedule_RA(module_idP, frame, slot, &sched_info->UL_dci_req, &sched_info->DL_req, &sched_info->TX_req); } // This schedules the DCI for Uplink and subsequently PUSCH - nr_schedule_ulsch(module_idP, frame, slot); + nr_schedule_ulsch(module_idP, frame, slot, &sched_info->UL_dci_req); // This schedules the DCI for Downlink and PDSCH start_meas(&gNB->schedule_dlsch); - nr_schedule_ue_spec(module_idP, frame, slot); + nr_schedule_ue_spec(module_idP, frame, slot, &sched_info->DL_req, &sched_info->TX_req); stop_meas(&gNB->schedule_dlsch); nr_sr_reporting(gNB, frame, slot); nr_schedule_pucch(gNB, frame, slot); + /* TODO: we copy from gNB->UL_tti_req_ahead[0][current_index], ie. CC_id == 0, + * is more than 1 CC supported? + */ + AssertFatal(MAX_NUM_CCs == 1, "only 1 CC supported\n"); + const int current_index = ul_buffer_index(frame, slot, *scc->ssbSubcarrierSpacing, gNB->UL_tti_req_ahead_size); + copy_ul_tti_req(&sched_info->UL_tti_req, &gNB->UL_tti_req_ahead[0][current_index]); + stop_meas(&gNB->eNB_scheduler); - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_OUT); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 587575241f..d08d2fefb3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -662,8 +662,13 @@ void nr_initiate_ra_proc(module_id_t module_idP, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0); } -void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { - +void nr_schedule_RA(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_ul_dci_request_t *ul_dci_req, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) +{ gNB_MAC_INST *mac = RC.nrmac[module_idP]; start_meas(&mac->schedule_ra); @@ -674,15 +679,15 @@ void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { LOG_D(NR_MAC, "RA[state:%d]\n", ra->state); switch (ra->state) { case Msg2: - nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra); + nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); break; case Msg3_retransmission: - nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra); + nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra, ul_dci_req); break; case Msg3_dcch_dtch: - nr_generate_Msg3_dcch_dtch_response(module_idP, CC_id, frameP, slotP, ra); + nr_generate_Msg3_dcch_dtch_response(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); case Msg4: - nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra); + nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); break; case WAIT_Msg4_ACK: nr_check_Msg4_Ack(module_idP, CC_id, frameP, slotP, ra); @@ -695,9 +700,13 @@ void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { stop_meas(&mac->schedule_ra); } - -void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra) { - +void nr_generate_Msg3_retransmission(module_id_t module_idP, + int CC_id, + frame_t frame, + sub_frame_t slot, + NR_RA_t *ra, + nfapi_nr_ul_dci_request_t *ul_dci_req) +{ gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; @@ -784,8 +793,6 @@ void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t NR_ControlResourceSet_t *coreset = ra->coreset; AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg3 retransmission\n"); - nfapi_nr_ul_dci_request_t *ul_dci_req = &nr_mac->UL_dci_req[CC_id]; - const int coresetid = coreset->controlResourceSetId; nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][coresetid]; if (!pdcch_pdu_rel15) { @@ -1148,8 +1155,14 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu); } -void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra) { - +void nr_generate_Msg2(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) +{ gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP; @@ -1198,7 +1211,7 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra } // Checking if the DCI allocation is feasible in current subframe - nfapi_nr_dl_tti_request_body_t *dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { LOG_I(NR_MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, ra->RA_rnti); return; @@ -1369,7 +1382,7 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra nr_mac->cset0_bwp_size); // DL TX request - nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs]; + nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; // Program UL processing for Msg3 nr_get_Msg3alloc(module_idP, CC_id, scc, slotP, frameP, ra, nr_mac->tdd_beam_association); @@ -1395,9 +1408,9 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra tx_req->PDU_index = pduindex; tx_req->num_TLV = 1; tx_req->TLVs[0].length = tx_req->PDU_length + 2; - nr_mac->TX_req[CC_id].SFN = frameP; - nr_mac->TX_req[CC_id].Number_of_PDUs++; - nr_mac->TX_req[CC_id].Slot = slotP; + TX_req->SFN = frameP; + TX_req->Number_of_PDUs++; + TX_req->Slot = slotP; // Mark the corresponding symbols RBs as used fill_pdcch_vrb_map(nr_mac, @@ -1600,7 +1613,13 @@ void prepare_dl_pdus(gNB_MAC_INST *nr_mac, LOG_D(NR_MAC,"numDlDci: %i\n", pdcch_pdu_rel15->numDlDci); } -void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra) +void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; @@ -1654,7 +1673,7 @@ void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, int CC_id, fram } // Checking if the DCI allocation is feasible in current subframe - nfapi_nr_dl_tti_request_body_t *dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { LOG_I(NR_MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, rnti); return; @@ -1734,15 +1753,15 @@ void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, int CC_id, fram 0, time_domain_assignment, CC_id, rnti, 0, mcsIndex, tb_scaling, pduindex, rbStart, rbSize); // DL TX request - nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs]; + nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; memcpy(tx_req->TLVs[0].value.direct, buf, sizeof(uint8_t) * tb_size); tx_req->PDU_length = tb_size; tx_req->PDU_index = pduindex; tx_req->num_TLV = 1; tx_req->TLVs[0].length = tb_size + 2; - nr_mac->TX_req[CC_id].SFN = frameP; - nr_mac->TX_req[CC_id].Number_of_PDUs++; - nr_mac->TX_req[CC_id].Slot = slotP; + TX_req->SFN = frameP; + TX_req->Number_of_PDUs++; + TX_req->Slot = slotP; // Mark the corresponding symbols and RBs as used fill_pdcch_vrb_map(nr_mac, @@ -1780,7 +1799,13 @@ void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, int CC_id, fram sched_ctrl->ul_failure = 0; } -void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra) +void nr_generate_Msg4(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; @@ -1854,7 +1879,7 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra } // Checking if the DCI allocation is feasible in current subframe - nfapi_nr_dl_tti_request_body_t *dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { LOG_I(NR_MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, ra->rnti); return; @@ -2006,15 +2031,15 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra T_INT(frameP), T_INT(slotP), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock, harq->tb_size)); // DL TX request - nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs]; + nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; memcpy(tx_req->TLVs[0].value.direct, harq->transportBlock, sizeof(uint8_t) * harq->tb_size); tx_req->PDU_length = harq->tb_size; tx_req->PDU_index = pduindex; tx_req->num_TLV = 1; tx_req->TLVs[0].length = harq->tb_size + 2; - nr_mac->TX_req[CC_id].SFN = frameP; - nr_mac->TX_req[CC_id].Number_of_PDUs++; - nr_mac->TX_req[CC_id].Slot = slotP; + TX_req->SFN = frameP; + TX_req->Number_of_PDUs++; + TX_req->Slot = slotP; // Mark the corresponding symbols and RBs as used fill_pdcch_vrb_map(nr_mac, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 121ad179cc..37ceeddbee 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -89,10 +89,10 @@ void schedule_ssb(frame_t frame, sub_frame_t slot, } -void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { +void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, nfapi_nr_dl_tti_request_t *DL_req) +{ gNB_MAC_INST *gNB = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc; - nfapi_nr_dl_tti_request_t *dl_tti_request; nfapi_nr_dl_tti_request_body_t *dl_req; NR_MIB_t *mib = RC.nrrrc[module_idP]->carrier.mib.message.choice.mib; uint8_t num_tdd_period,num_ssb; @@ -103,8 +103,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) cc = &gNB->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; const int slots_per_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - dl_tti_request = &gNB->DL_req[CC_id]; - dl_req = &dl_tti_request->dl_tti_request_body; + dl_req = &DL_req->dl_tti_request_body; // get MIB every 8 frames if(((slotP == 0) && (frameP & 7) == 0) || @@ -255,7 +254,6 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) } } - void schedule_nr_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { //---------------------------------------- } @@ -520,8 +518,12 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, } -void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { - +void schedule_nr_sib1(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) +{ // TODO: Get these values from RRC const int CC_id = 0; uint8_t candidate_idx = 0; @@ -586,12 +588,12 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) candidate_idx, sib1_sdu_length); - nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; int pdu_index = gNB_mac->pdu_index[0]++; nr_fill_nfapi_dl_sib1_pdu(module_idP, dl_req, pdu_index, type0_PDCCH_CSS_config, TBS, tda_info.startSymbolIndex, tda_info.nrOfSymbols); - const int ntx_req = gNB_mac->TX_req[CC_id].Number_of_PDUs; - nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[ntx_req]; + const int ntx_req = TX_req->Number_of_PDUs; + nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req]; // Data to be transmitted memcpy(tx_req->TLVs[0].value.direct, sib1_payload, TBS); @@ -600,9 +602,9 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) tx_req->PDU_index = pdu_index; tx_req->num_TLV = 1; tx_req->TLVs[0].length = TBS + 2; - gNB_mac->TX_req[CC_id].Number_of_PDUs++; - gNB_mac->TX_req[CC_id].SFN = frameP; - gNB_mac->TX_req[CC_id].Slot = slotP; + TX_req->Number_of_PDUs++; + TX_req->SFN = frameP; + TX_req->Slot = slotP; type0_PDCCH_CSS_config->active = false; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 7d3cd511e9..e6f32b1405 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -873,8 +873,10 @@ nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(int CC_id) { void nr_schedule_ue_spec(module_id_t module_id, frame_t frame, - sub_frame_t slot) { - + sub_frame_t slot, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) +{ gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; if (!is_xlsch_in_slot(gNB_mac->dlsch_slot_bitmap[slot / 64], slot)) @@ -885,7 +887,7 @@ void nr_schedule_ue_spec(module_id_t module_id, const int CC_id = 0; NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon; NR_UEs_t *UE_info = &gNB_mac->UE_info; - nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; UE_iterator(UE_info->list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; @@ -1326,16 +1328,16 @@ void nr_schedule_ue_spec(module_id_t module_id, T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock, TBS)); } - const int ntx_req = gNB_mac->TX_req[CC_id].Number_of_PDUs; - nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[ntx_req]; + const int ntx_req = TX_req->Number_of_PDUs; + nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req]; tx_req->PDU_length = TBS; tx_req->PDU_index = pduindex; tx_req->num_TLV = 1; tx_req->TLVs[0].length = TBS + 2; memcpy(tx_req->TLVs[0].value.direct, harq->transportBlock, TBS); - gNB_mac->TX_req[CC_id].Number_of_PDUs++; - gNB_mac->TX_req[CC_id].SFN = frame; - gNB_mac->TX_req[CC_id].Slot = slot; + TX_req->Number_of_PDUs++; + TX_req->SFN = frame; + TX_req->Slot = slot; /* mark UE as scheduled */ sched_pdsch->rbSize = 0; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 09d4d95458..99ce0ab235 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2538,11 +2538,8 @@ int get_pdsch_to_harq_feedback(NR_PUCCH_Config_t *pucch_Config, } } -void nr_csirs_scheduling(int Mod_idP, - frame_t frame, - sub_frame_t slot, - int n_slots_frame){ - +void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slots_frame, nfapi_nr_dl_tti_request_t *DL_req) +{ int CC_id = 0; NR_UEs_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; gNB_MAC_INST *gNB_mac = RC.nrmac[Mod_idP]; @@ -2581,7 +2578,7 @@ void nr_csirs_scheduling(int Mod_idP, NR_NZP_CSI_RS_Resource_t *nzpcsi; int period, offset; - nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; for (int id = 0; id < csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.count; id++){ nzpcsi = csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.array[id]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 09aad3d9cb..3c314c6c86 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1997,7 +1997,7 @@ nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(int CC_id) return nr_fr1_ulsch_preprocessor; } -void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) +void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, nfapi_nr_ul_dci_request_t *ul_dci_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; /* Uplink data ONLY can be scheduled when the current slot is downlink slot, @@ -2010,8 +2010,6 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) if (!do_sched) return; - const int CC_id = 0; - nfapi_nr_ul_dci_request_t *ul_dci_req = &nr_mac->UL_dci_req[CC_id]; ul_dci_req->SFN = frame; ul_dci_req->Slot = slot; /* a PDCCH PDU groups DCIs per BWP and CORESET. Save a pointer to each diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index b62984943c..a700c5c652 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -60,17 +60,19 @@ bool nr_mac_prepare_ra_nsa_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupCo bool nr_mac_update_cellgroup(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); bool nr_mac_update_RA(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); -void clear_nr_nfapi_information(gNB_MAC_INST * gNB, +void clear_nr_nfapi_information(gNB_MAC_INST *gNB, int CC_idP, - frame_t frameP, - sub_frame_t subframeP); + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req, + nfapi_nr_ul_dci_request_t *UL_dci_req); void nr_mac_update_timers(module_id_t module_id, frame_t frame, sub_frame_t slot); -void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, - frame_t frame_rxP, sub_frame_t slot_rxP); +void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame_rxP, sub_frame_t slot_rxP, NR_Sched_Rsp_t *sched_info); void schedule_nr_bwp_switch(module_id_t module_id, frame_t frame, @@ -81,7 +83,9 @@ void schedule_nr_bwp_switch(module_id_t module_id, * messages, statistics, HARQ handling, CEs, ... */ void nr_schedule_ue_spec(module_id_t module_id, frame_t frame, - sub_frame_t slot); + sub_frame_t slot, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req); uint32_t schedule_control_sib1(module_id_t module_id, int CC_id, @@ -95,21 +99,30 @@ uint32_t schedule_control_sib1(module_id_t module_id, /* \brief default FR1 DL preprocessor init routine, returns preprocessor to call */ nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(int CC_id); -void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP); +void schedule_nr_sib1(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req); -void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP); +void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, nfapi_nr_dl_tti_request_t *DL_req); /* \brief main UL scheduler function. Calls a preprocessor to decide on * resource allocation, then "post-processes" resource allocation (nFAPI * messages, statistics, HARQ handling, ... */ -void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot); +void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, nfapi_nr_ul_dci_request_t *ul_dci_req); /* \brief default FR1 UL preprocessor init routine, returns preprocessor to call */ nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(int CC_id); /////// Random Access MAC-PHY interface functions and primitives /////// -void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP); +void nr_schedule_RA(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_ul_dci_request_t *ul_dci_req, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req); /* \brief Function to indicate a received preamble on PRACH. It initiates the RA procedure. @param module_idP Instance ID of gNB @@ -134,7 +147,12 @@ void nr_get_Msg3alloc(module_id_t module_id, NR_RA_t *ra, int16_t *tdd_beam_association); -void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra); +void nr_generate_Msg3_retransmission(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_ul_dci_request_t *ul_dci_req); /* \brief Function in gNB to fill RAR pdu when requested by PHY. @param ra Instance of RA resources of gNB @@ -201,10 +219,7 @@ void nr_srs_ri_computation(const nfapi_nr_srs_normalized_channel_iq_matrix_t *nr void nr_schedule_srs(int module_id, frame_t frame, int slot); -void nr_csirs_scheduling(int Mod_idP, - frame_t frame, - sub_frame_t slot, - int n_slots_frame); +void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slots_frame, nfapi_nr_dl_tti_request_t *DL_req); void nr_csi_meas_reporting(int Mod_idP, frame_t frameP, @@ -365,13 +380,31 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, unsigned char drx_cmd, unsigned char *ue_cont_res_id); -void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra); +void nr_generate_Msg2(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *dl_req, + nfapi_nr_tx_data_request_t *TX_req); -void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra); +void nr_generate_Msg4(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req); void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra); -void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra); +void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req); int binomial(int n, int k); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 96734aa8b1..1cd0f89736 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -719,24 +719,15 @@ typedef struct gNB_MAC_INST_s { uint16_t ulprbbl[MAX_BWP_SIZE]; /// NFAPI Config Request Structure nfapi_nr_config_request_scf_t config[NFAPI_CC_MAX]; - /// NFAPI DL Config Request Structure - nfapi_nr_dl_tti_request_t DL_req[NFAPI_CC_MAX]; /// a PDCCH PDU groups DCIs per BWP and CORESET. The following structure /// keeps pointers to PDCCH PDUs within DL_req so that we can easily track /// PDCCH PDUs per CC/BWP/CORESET nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_idx[NFAPI_CC_MAX][MAX_NUM_CORESET]; - /// NFAPI UL TTI Request Structure, simple pointer into structure - /// UL_tti_req_ahead for current frame/slot - nfapi_nr_ul_tti_request_t *UL_tti_req[NFAPI_CC_MAX]; /// NFAPI UL TTI Request Structure for future TTIs, dynamically allocated /// because length depends on number of slots nfapi_nr_ul_tti_request_t *UL_tti_req_ahead[NFAPI_CC_MAX]; int UL_tti_req_ahead_size; int vrb_map_UL_size; - /// NFAPI HI/DCI0 Config Request Structure - nfapi_nr_ul_dci_request_t UL_dci_req[NFAPI_CC_MAX]; - /// NFAPI DL PDU structure - nfapi_nr_tx_data_request_t TX_req[NFAPI_CC_MAX]; NR_UEs_t UE_info; diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 60db353949..117b028c9a 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -39,12 +39,12 @@ #include "nfapi/oai_integration/vendor_ext.h" #include "nfapi/oai_integration/gnb_ind_vars.h" #include "openair2/PHY_INTERFACE/queue_t.h" +#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h" #define MAX_IF_MODULES 100 //#define UL_HARQ_PRINT static NR_IF_Module_t *nr_if_inst[MAX_IF_MODULES]; -static NR_Sched_Rsp_t NR_Sched_INFO[MAX_IF_MODULES][MAX_NUM_CCs]; extern int oai_nfapi_harq_indication(nfapi_harq_indication_t *harq_ind); extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind); extern int oai_nfapi_cqi_indication(nfapi_cqi_indication_t *cqi_ind); @@ -389,7 +389,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { AssertFatal(UL_info!=NULL,"UL_info is null\n"); module_id_t module_id = UL_info->module_id; int CC_id = UL_info->CC_id; - NR_Sched_Rsp_t *sched_info = &NR_Sched_INFO[module_id][CC_id]; + NR_Sched_Rsp_t *sched_info; NR_IF_Module_t *ifi = nr_if_inst[module_id]; LOG_D(NR_PHY,"SFN/SLOT:%d.%d module_id:%d CC_id:%d UL_info[rach_pdus:%zu rx_ind:%zu crcs:%zu]\n", @@ -451,8 +451,6 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { } if (NFAPI_MODE != NFAPI_MODE_PNF) { gNB_MAC_INST *mac = RC.nrmac[module_id]; - // clear UL DCI prior to handling ULSCH - mac->UL_dci_req[CC_id].numPdus = 0; if (ifi->CC_mask==0) { ifi->current_frame = UL_info->frame; ifi->current_slot = UL_info->slot; @@ -471,21 +469,20 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { */ nfapi_nr_config_request_scf_t *cfg = &mac->config[CC_id]; int spf = get_spf(cfg); + sched_info = allocate_sched_response(); + // clear UL DCI prior to handling ULSCH + sched_info->UL_dci_req.numPdus = 0; gNB_dlsch_ulsch_scheduler(module_id, - (UL_info->frame+((UL_info->slot>(spf-1-ifi->sl_ahead))?1:0)) % 1024, - (UL_info->slot+ifi->sl_ahead)%spf); + (UL_info->frame + ((UL_info->slot > (spf - 1 - ifi->sl_ahead)) ? 1 : 0)) % 1024, + (UL_info->slot + ifi->sl_ahead) % spf, + sched_info); ifi->CC_mask = 0; sched_info->module_id = module_id; sched_info->CC_id = CC_id; sched_info->frame = (UL_info->frame + ((UL_info->slot>(spf-1-ifi->sl_ahead)) ? 1 : 0)) % 1024; sched_info->slot = (UL_info->slot+ifi->sl_ahead)%spf; - sched_info->DL_req = &mac->DL_req[CC_id]; - sched_info->UL_dci_req = &mac->UL_dci_req[CC_id]; - sched_info->UL_tti_req = mac->UL_tti_req[CC_id]; - - sched_info->TX_req = &mac->TX_req[CC_id]; #ifdef DUMP_FAPI dump_dl(sched_info); #endif @@ -496,10 +493,11 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { CC_id); ifi->NR_Schedule_response(sched_info); - LOG_D(NR_PHY,"NR_Schedule_response: SFN SLOT:%d %d dl_pdus:%d\n", - sched_info->frame, - sched_info->slot, - sched_info->DL_req->dl_tti_request_body.nPDUs); + LOG_D(NR_PHY, + "NR_Schedule_response: SFN SLOT:%d %d dl_pdus:%d\n", + sched_info->frame, + sched_info->slot, + sched_info->DL_req.dl_tti_request_body.nPDUs); } } } @@ -520,5 +518,7 @@ NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { "allocation of nr_if_inst[%d]->if_mutex fails\n",Mod_id); } + init_sched_response(); + return nr_if_inst[Mod_id]; } diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_PHY_INTERFACE/NR_IF_Module.h index 47e961da2b..f85d44398f 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.h +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.h @@ -83,6 +83,8 @@ typedef struct { typedef struct { + /// the ID of this sched_response - used by sched_reponse memory management + int sched_response_id; /// Module ID module_id_t module_id; /// CC ID @@ -92,13 +94,13 @@ typedef struct { /// slot slot_t slot; /// nFAPI DL Config Request - nfapi_nr_dl_tti_request_t *DL_req; + nfapi_nr_dl_tti_request_t DL_req; /// nFAPI UL Config Request - nfapi_nr_ul_tti_request_t *UL_tti_req; + nfapi_nr_ul_tti_request_t UL_tti_req; /// nFAPI UL_DCI Request - nfapi_nr_ul_dci_request_t *UL_dci_req; + nfapi_nr_ul_dci_request_t UL_dci_req; /// Pointers to DL SDUs - nfapi_nr_tx_data_request_t *TX_req; + nfapi_nr_tx_data_request_t TX_req; } NR_Sched_Rsp_t; typedef struct { diff --git a/openair2/NR_PHY_INTERFACE/nr_sched_response.c b/openair2/NR_PHY_INTERFACE/nr_sched_response.c new file mode 100644 index 0000000000..f0aa25781c --- /dev/null +++ b/openair2/NR_PHY_INTERFACE/nr_sched_response.c @@ -0,0 +1,153 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/* sched response memory management */ + +/* A system with reference counting is implemented. + * It is needed because several threads will access the structure, + * which has to be released only when all the threads are done with it. + * So the main thread allocates a sched_response with allocate_sched_response() + * which allocates a sched_response with a reference counter == 1 + * and then for each other thread that will access sched_response, a + * call to inc_ref_sched_response() is done. When a thread has finished + * using the sched_response, it calls deref_sched_response() which will + * in turn call release_sched_response() when the reference counter becomes 0. + * + * The several threads in question are accessing the _same_ sched_response, + * it has not to be confused with the various TX processes that may run in + * parallel and which are accessing _different_ sched_response (the maximum + * number of parallel processes is N_RESP). + */ + +#include "nr_sched_response.h" + +#include +#include + +#include "common/utils/LOG/log.h" +#include "common/utils/assertions.h" + +#define N_RESP 3 +static NR_Sched_Rsp_t resp[N_RESP]; +static int resp_refcount[N_RESP]; +static int resp_freelist_next[N_RESP]; +static int resp_freelist_head; +static pthread_mutex_t resp_mutex = PTHREAD_MUTEX_INITIALIZER; +static bool resp_freelist_inited = false; + +void init_sched_response(void) +{ + /* init only once */ + if (pthread_mutex_lock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_lock failed\n"); + if (resp_freelist_inited) { + if (pthread_mutex_unlock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_unlock failed\n"); + return; + } + resp_freelist_inited = true; + if (pthread_mutex_unlock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_unlock failed\n"); + + int i; + for (i = 0; i < N_RESP - 1; i++) + resp_freelist_next[i] = i + 1; + resp_freelist_next[N_RESP - 1] = -1; + resp_freelist_head = 0; +} + +NR_Sched_Rsp_t *allocate_sched_response(void) +{ + NR_Sched_Rsp_t *ret; + int new_head; + + if (pthread_mutex_lock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_lock failed\n"); + + AssertFatal(resp_freelist_inited, "sched_response used before init\n"); + + if (resp_freelist_head == -1) { + LOG_E(PHY, "fatal: sched_response cannot be allocated, increase N_RESP\n"); + exit(1); + } + + ret = &resp[resp_freelist_head]; + ret->sched_response_id = resp_freelist_head; + resp_refcount[resp_freelist_head] = 1; + + new_head = resp_freelist_next[resp_freelist_head]; + resp_freelist_next[resp_freelist_head] = -1; + resp_freelist_head = new_head; + + if (pthread_mutex_unlock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_unlock failed\n"); + + return ret; +} + +static void release_sched_response(int sched_response_id) +{ + resp_freelist_next[sched_response_id] = resp_freelist_head; + resp_freelist_head = sched_response_id; +} + +void deref_sched_response(int sched_response_id) +{ + /* simulators (ulsim/dlsim) deal with their own sched_response but call + * functions that call this one, let's handle this case with a special + * value -1 where we do nothing (yes it's a hack) + */ + if (sched_response_id == -1) + return; + + if (pthread_mutex_lock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_lock failed\n"); + + AssertFatal(resp_freelist_inited, "sched_response used before init\n"); + AssertFatal(resp_refcount[sched_response_id] > 0, "sched_reponse decreased too much\n"); + + resp_refcount[sched_response_id]--; + if (resp_refcount[sched_response_id] == 0) + release_sched_response(sched_response_id); + + if (pthread_mutex_unlock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_unlock failed\n"); +} + +void inc_ref_sched_response(int sched_response_id) +{ + /* simulators (ulsim/dlsim) deal with their own sched_response but call + * functions that call this one, let's handle this case with a special + * value -1 where we do nothing (yes it's a hack) + */ + if (sched_response_id == -1) + return; + + if (pthread_mutex_lock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_lock failed\n"); + + AssertFatal(resp_freelist_inited, "sched_response used before init\n"); + + resp_refcount[sched_response_id]++; + + if (pthread_mutex_unlock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_unlock failed\n"); +} diff --git a/openair2/NR_PHY_INTERFACE/nr_sched_response.h b/openair2/NR_PHY_INTERFACE/nr_sched_response.h new file mode 100644 index 0000000000..33a0af93d0 --- /dev/null +++ b/openair2/NR_PHY_INTERFACE/nr_sched_response.h @@ -0,0 +1,32 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef OPENAIR2_NR_PHY_INTERFACE_NR_SCHED_RESPONSE_H +#define OPENAIR2_NR_PHY_INTERFACE_NR_SCHED_RESPONSE_H + +#include "NR_IF_Module.h" + +void init_sched_response(void); +NR_Sched_Rsp_t *allocate_sched_response(void); +void deref_sched_response(int sched_response_id); +void inc_ref_sched_response(int sched_response_id); + +#endif /* OPENAIR2_NR_PHY_INTERFACE_NR_SCHED_RESPONSE_H */ diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 5ddd59fcc1..6aa44194a3 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -66,6 +66,7 @@ queue_t nr_dl_tti_req_queue; queue_t nr_tx_req_queue; queue_t nr_ul_dci_req_queue; queue_t nr_ul_tti_req_queue; +pthread_mutex_t mac_IF_mutex; void nrue_init_standalone_socket(int tx_port, int rx_port) { @@ -304,25 +305,24 @@ static void fill_dl_info_with_pdcch(fapi_nr_dci_indication_t *dci, nfapi_nr_dl_d static void fill_mib_in_rx_ind(nfapi_nr_dl_tti_request_pdu_t *pdu_list, fapi_nr_rx_indication_t *rx_ind, int pdu_idx, int pdu_type) { - AssertFatal(pdu_idx < sizeof(rx_ind->rx_indication_body) / sizeof(rx_ind->rx_indication_body[0]), - "pdu_index (%d) is greater than rx_indication_body size!\n", pdu_idx); - AssertFatal(pdu_idx == rx_ind->number_pdus, "Invalid pdu_idx %d!\n", pdu_idx); + AssertFatal(pdu_idx < sizeof(rx_ind->rx_indication_body) / sizeof(rx_ind->rx_indication_body[0]), + "pdu_index (%d) is greater than rx_indication_body size!\n", pdu_idx); + AssertFatal(pdu_idx == rx_ind->number_pdus, "Invalid pdu_idx %d!\n", pdu_idx); - LOG_T(NR_MAC, "Recevied an SSB and are filling rx_ind with the MIB!\n"); - - nfapi_nr_dl_tti_ssb_pdu_rel15_t *ssb_pdu = &pdu_list->ssb_pdu.ssb_pdu_rel15; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.cell_id = ssb_pdu->PhysCellId; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu = MALLOC(3 * sizeof(*rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu)); - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[0] = (ssb_pdu->bchPayload) & 0xff; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[1] = (ssb_pdu->bchPayload >> 8) & 0xff; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[2] = (ssb_pdu->bchPayload >> 16) & 0xff; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.rsrp_dBm = ssb_pdu->ssbRsrp; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_index = ssb_pdu->SsbBlockIndex; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_length = pdu_list->PDUSize; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_start_subcarrier = ssb_pdu->SsbSubcarrierOffset; - rx_ind->rx_indication_body[pdu_idx].pdu_type = pdu_type; - rx_ind->number_pdus = pdu_idx + 1; + LOG_T(NR_MAC, "Recevied an SSB and are filling rx_ind with the MIB!\n"); + nfapi_nr_dl_tti_ssb_pdu_rel15_t *ssb_pdu = &pdu_list->ssb_pdu.ssb_pdu_rel15; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.cell_id = ssb_pdu->PhysCellId; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[0] = (ssb_pdu->bchPayload) & 0xff; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[1] = (ssb_pdu->bchPayload >> 8) & 0xff; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[2] = (ssb_pdu->bchPayload >> 16) & 0xff; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.rsrp_dBm = ssb_pdu->ssbRsrp; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_index = ssb_pdu->SsbBlockIndex; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_length = pdu_list->PDUSize; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_start_subcarrier = ssb_pdu->SsbSubcarrierOffset; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.decoded_pdu = true; + rx_ind->rx_indication_body[pdu_idx].pdu_type = pdu_type; + rx_ind->number_pdus = pdu_idx + 1; } static bool is_my_dci(NR_UE_MAC_INST_t *mac, nfapi_nr_dl_dci_pdu_t *received_pdu) @@ -692,7 +692,6 @@ void check_and_process_dci(nfapi_nr_dl_tti_request_t *dl_tti_request, slot = dl_tti_request->Slot; LOG_D(NR_PHY, "[%d, %d] dl_tti_request\n", frame, slot); copy_dl_tti_req_to_dl_info(&mac->dl_info, dl_tti_request); - free_and_zero(dl_tti_request); } /* This checks if the previously recevied DCI matches our current RNTI value. The assumption is that if the DCI matches our RNTI, then the @@ -711,14 +710,12 @@ void check_and_process_dci(nfapi_nr_dl_tti_request_t *dl_tti_request, else { LOG_D(NR_MAC, "Unexpected tx_data_req\n"); } - free_and_zero(tx_data_request); } else if (ul_dci_request) { frame = ul_dci_request->SFN; slot = ul_dci_request->Slot; LOG_D(NR_PHY, "[%d, %d] ul_dci_request\n", frame, slot); copy_ul_dci_data_req_to_dl_info(&mac->dl_info, ul_dci_request); - free_and_zero(ul_dci_request); } else if (ul_tti_request) { frame = ul_tti_request->SFN; @@ -735,7 +732,10 @@ void check_and_process_dci(nfapi_nr_dl_tti_request_t *dl_tti_request, NR_UL_TIME_ALIGNMENT_t ul_time_alignment; memset(&ul_time_alignment, 0, sizeof(ul_time_alignment)); - fill_dci_from_dl_config(&mac->dl_info, &mac->dl_config_request); + if (dl_tti_request || tx_data_request || ul_dci_request) { + fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, slot); + fill_dci_from_dl_config(&mac->dl_info, dl_config); + } nr_ue_dl_scheduler(&mac->dl_info); nr_ue_dl_indication(&mac->dl_info, &ul_time_alignment); @@ -1045,18 +1045,26 @@ int handle_bcch_bch(module_id_t module_id, int cc_id, uint16_t ssb_start_subcarrier, uint16_t cell_id){ return nr_ue_decode_mib(module_id, - cc_id, - gNB_index, - phy_data, - additional_bits, - ssb_length, // Lssb = 64 is not support - ssb_index, - pduP, - ssb_start_subcarrier, - cell_id); + cc_id, + gNB_index, + phy_data, + additional_bits, + ssb_length, // Lssb = 64 is not support + ssb_index, + pduP, + ssb_start_subcarrier, + cell_id); } +void handle_bch_failure(NR_UE_MAC_INST_t *mac) +{ + mac->ssb_measurements.consecutive_bch_failures++; + //TODO handle this properly by scheduling re-synchronization + AssertFatal(mac->ssb_measurements.consecutive_bch_failures < 100, + "Radio link failure caused by 100 consecutive PBCH detection failures.\n"); +} + // L2 Abstraction Layer int handle_bcch_dlsch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint8_t ack_nack, uint8_t *pduP, uint32_t pdu_len){ return nr_ue_decode_BCCH_DL_SCH(module_id, cc_id, gNB_index, ack_nack, pduP, pdu_len); @@ -1069,10 +1077,10 @@ int handle_dci(module_id_t module_id, int cc_id, unsigned int gNB_index, frame_t } -void handle_ssb_meas(NR_UE_MAC_INST_t *mac, uint8_t ssb_index, int16_t rsrp_dbm) +void handle_ssb_meas(NR_UE_MAC_INST_t *mac, uint8_t ssb_index, int16_t rsrp_dbm) { - mac->phy_measurements.ssb_index = ssb_index; - mac->phy_measurements.ssb_rsrp_dBm = rsrp_dbm; + mac->ssb_measurements.ssb_index = ssb_index; + mac->ssb_measurements.ssb_rsrp_dBm = rsrp_dbm; } // L2 Abstraction Layer @@ -1116,6 +1124,9 @@ void update_harq_status(module_id_t module_id, uint8_t harq_pid, uint8_t ack_nac int nr_ue_ul_indication(nr_uplink_indication_t *ul_info) { + + pthread_mutex_lock(&mac_IF_mutex); + module_id_t module_id = ul_info->module_id; NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); @@ -1125,15 +1136,19 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info) NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon = mac->scc != NULL ? mac->scc->tdd_UL_DL_ConfigurationCommon : mac->scc_SIB->tdd_UL_DL_ConfigurationCommon; if (mac->phy_config_request_sent && is_nr_UL_slot(tdd_UL_DL_ConfigurationCommon, ul_info->slot_tx, mac->frame_type)) nr_ue_ul_scheduler(ul_info); + + pthread_mutex_unlock(&mac_IF_mutex); + return 0; } int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment){ + pthread_mutex_lock(&mac_IF_mutex); uint32_t ret_mask = 0x0; module_id_t module_id = dl_info->module_id; NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; + fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, dl_info->slot); if ((!dl_info->dci_ind && !dl_info->rx_ind)) { // UL indication to schedule DCI reception @@ -1160,7 +1175,7 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ LOG_D(NR_MAC, "We are filtering a UL_DCI to prevent it from being treated like a DL_DCI\n"); continue; } - dci_pdu_rel15_t *def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[dci_index->dci_format]; + dci_pdu_rel15_t *def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[dl_info->slot][dci_index->dci_format]; g_harq_pid = def_dci_pdu_rel15->harq_pid; LOG_T(NR_MAC, "Setting harq_pid = %d and dci_index = %d (based on format)\n", g_harq_pid, dci_index->dci_format); @@ -1180,31 +1195,35 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ for (int i=0; irx_ind->number_pdus; ++i) { + fapi_nr_rx_indication_body_t rx_indication_body = dl_info->rx_ind->rx_indication_body[i]; LOG_D(NR_MAC, "In %s sending DL indication to MAC. 1 PDU type %d of %d total number of PDUs \n", __FUNCTION__, - dl_info->rx_ind->rx_indication_body[i].pdu_type, + rx_indication_body.pdu_type, dl_info->rx_ind->number_pdus); - switch(dl_info->rx_ind->rx_indication_body[i].pdu_type){ + switch(rx_indication_body.pdu_type){ case FAPI_NR_RX_PDU_TYPE_SSB: - handle_ssb_meas(mac, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_index, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.rsrp_dBm); - ret_mask |= (handle_bcch_bch(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, dl_info->phy_data, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.pdu, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.additional_bits, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_index, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_length, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_start_subcarrier, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.cell_id)) << FAPI_NR_RX_PDU_TYPE_SSB; - free((dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.pdu); + if(rx_indication_body.ssb_pdu.decoded_pdu) { + handle_ssb_meas(mac, + rx_indication_body.ssb_pdu.ssb_index, + rx_indication_body.ssb_pdu.rsrp_dBm); + ret_mask |= (handle_bcch_bch(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, dl_info->phy_data, + rx_indication_body.ssb_pdu.pdu, + rx_indication_body.ssb_pdu.additional_bits, + 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.cell_id)) << FAPI_NR_RX_PDU_TYPE_SSB; + } + else + handle_bch_failure(mac); break; case FAPI_NR_RX_PDU_TYPE_SIB: ret_mask |= (handle_bcch_dlsch(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, - (dl_info->rx_ind->rx_indication_body+i)->pdsch_pdu.ack_nack, - (dl_info->rx_ind->rx_indication_body+i)->pdsch_pdu.pdu, - (dl_info->rx_ind->rx_indication_body+i)->pdsch_pdu.pdu_length)) << FAPI_NR_RX_PDU_TYPE_SIB; + rx_indication_body.pdsch_pdu.ack_nack, + rx_indication_body.pdsch_pdu.pdu, + rx_indication_body.pdsch_pdu.pdu_length)) << FAPI_NR_RX_PDU_TYPE_SIB; break; case FAPI_NR_RX_PDU_TYPE_DLSCH: ret_mask |= (handle_dlsch(dl_info, ul_time_alignment, i)) << FAPI_NR_RX_PDU_TYPE_DLSCH; @@ -1216,16 +1235,16 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ ret_mask |= (handle_csirs_measurements(dl_info->module_id, dl_info->frame, dl_info->slot, - &(dl_info->rx_ind->rx_indication_body+i)->csirs_measurements)) << FAPI_NR_CSIRS_IND; + &rx_indication_body.csirs_measurements)) << FAPI_NR_CSIRS_IND; break; default: break; } } - free(dl_info->rx_ind); dl_info->rx_ind = NULL; } } + pthread_mutex_unlock(&mac_IF_mutex); return 0; } @@ -1247,6 +1266,7 @@ nr_ue_if_module_t *nr_ue_if_module_init(uint32_t module_id){ nr_ue_if_module_inst[module_id]->dl_indication = nr_ue_dl_indication; nr_ue_if_module_inst[module_id]->ul_indication = nr_ue_ul_indication; } + pthread_mutex_init(&mac_IF_mutex, NULL); return nr_ue_if_module_inst[module_id]; } @@ -1263,8 +1283,8 @@ int nr_ue_dcireq(nr_dcireq_t *dcireq) { fapi_nr_dl_config_request_t *dl_config = &dcireq->dl_config_req; NR_UE_MAC_INST_t *UE_mac = get_mac_inst(0); - dl_config->sfn = UE_mac->dl_config_request.sfn; - dl_config->slot = UE_mac->dl_config_request.slot; + dl_config->sfn = dcireq->frame; + dl_config->slot = dcireq->slot; LOG_T(PHY, "Entering UE DCI configuration frame %d slot %d \n", dcireq->frame, dcireq->slot); diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index e53ad60685..f8d69e942a 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -271,6 +271,40 @@ typedef struct pdu_session_param_s { uint8_t cause_value; } rrc_pdu_session_param_t; +typedef struct drb_s { + int status; + int defaultDRBid; + int drb_id; + int reestablishPDCP; + int recoverPDCP; + int daps_Config_r16; + struct cnAssociation_s { + int present; + int eps_BearerIdentity; + struct sdap_config_s { + bool defaultDRB; + int pdusession_id; + int sdap_HeaderDL; + int sdap_HeaderUL; + int mappedQoS_FlowsToAdd[QOSFLOW_MAX_VALUE]; + } sdap_config; + } cnAssociation; + struct pdcp_config_s { + int discardTimer; + int pdcp_SN_SizeUL; + int pdcp_SN_SizeDL; + int t_Reordering; + int integrityProtection; + struct headerCompression_s { + int NotUsed; + int present; + } headerCompression; + struct ext1_s { + int cipheringDisabled; + } ext1; + } pdcp_config; +} drb_t; + typedef struct gNB_RRC_UE_s { uint8_t primaryCC_id; NR_SRB_ToAddModList_t *SRB_configList; @@ -278,6 +312,7 @@ typedef struct gNB_RRC_UE_s { NR_DRB_ToAddModList_t *DRB_configList; NR_DRB_ToAddModList_t *DRB_configList2[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER]; NR_DRB_ToReleaseList_t *DRB_Release_configList2[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER]; + drb_t established_drbs[NGAP_MAX_DRBS_PER_UE]; uint8_t DRB_active[NGAP_MAX_DRBS_PER_UE]; NR_SRB_INFO_TABLE_ENTRY Srb[maxSRBs]; // 3gpp max is 3 SRBs, number 1..3, we waste the entry 0 for code simplicity diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 8bdc83d58a..f9447fc57a 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -643,7 +643,8 @@ void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, if(drb_is_active(ue_p, drb_id)){ /* Non-GBR flow using the same DRB or a GBR flow with no available DRBs*/ nb_drb_to_setup--; } else { - NR_DRB_ToAddMod_t *DRB_config = generateDRB(ue_p, drb_id, &ue_p->pduSession[i], rrc->configuration.enable_sdap, rrc->security.do_drb_integrity, rrc->security.do_drb_ciphering); + generateDRB(ue_p, drb_id, &ue_p->pduSession[i], rrc->configuration.enable_sdap, rrc->security.do_drb_integrity, rrc->security.do_drb_ciphering); + NR_DRB_ToAddMod_t *DRB_config = generateDRB_ASN1(&ue_p->established_drbs[drb_id-1]); if (drb_id_to_setup_start == 0) drb_id_to_setup_start = DRB_config->drb_Identity; asn1cSeqAdd(&ue_p->DRB_configList->list, DRB_config); @@ -1279,39 +1280,38 @@ void rrc_gNB_generate_RRCReestablishment(const protocol_ctxt_t *ctxt_pP, nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc); } -//----------------------------------------------------------------------------- -void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctxt_pP, const rnti_t reestablish_rnti, rrc_gNB_ue_context_t *ue_context_pP, const uint8_t xid) -//----------------------------------------------------------------------------- +/* + * Handle RRC Reestablishment Complete Functions + */ + +/// @brief Function used in RRCReestablishmentComplete procedure to reestablish the SRB2. +/// @param old_xid The old RRC transaction id. +/// @param new_xid The new RRC transaction id. +void RRCReestablishmentComplete_fill_SRB2_configList(const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP, + const uint8_t old_xid, + const uint8_t new_xid) { gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - LOG_I(NR_RRC, "[RAPROC] UE %04x Logical Channel UL-DCCH, processing NR_RRCReestablishmentComplete from UE (SRB1 Active)\n", ue_p->rnti); - - NR_DRB_ToAddModList_t *DRB_configList = ue_p->DRB_configList; + NR_SRB_ToAddMod_t *SRB2_config = NULL; NR_SRB_ToAddModList_t *SRB_configList = ue_p->SRB_configList; - NR_SRB_ToAddModList_t **SRB_configList2 = NULL; - NR_DRB_ToAddModList_t **DRB_configList2 = NULL; - NR_SRB_ToAddMod_t *SRB2_config = NULL; - NR_DRB_ToAddMod_t *DRB_config = NULL; - //NR_SDAP_Config_t *sdap_config = NULL; - int i = 0; + NR_SRB_ToAddModList_t **SRB_configList2 = NULL; - uint8_t new_xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); - int ret = 0; - ue_p->StatusRrc = NR_RRC_CONNECTED; - ue_p->ue_rrc_inactivity_timer = 1; // set rrc inactivity when UE goes into RRC_CONNECTED - ue_p->reestablishment_xid = new_xid; - SRB_configList2 = &ue_p->SRB_configList2[xid]; + SRB_configList2 = &ue_p->SRB_configList2[old_xid]; // get old configuration of SRB2 if (*SRB_configList2 != NULL) { - if((*SRB_configList2)->list.count!=0) { - LOG_D(NR_RRC, "SRB_configList2(%p) count is %d\n SRB_configList2->list.array[0] addr is %p", - SRB_configList2, (*SRB_configList2)->list.count, (*SRB_configList2)->list.array[0]); + if ((*SRB_configList2)->list.count != 0) { + LOG_D(NR_RRC, + "RRC Reestablishment - SRB_configList2(%p) count is %d\n SRB_configList2->list.array[0] addr is %p\n", + SRB_configList2, + (*SRB_configList2)->list.count, + (*SRB_configList2)->list.array[0]); } - for (i = 0; (i < (*SRB_configList2)->list.count) && (i < 3); i++) { - if ((*SRB_configList2)->list.array[i]->srb_Identity == 2 ) { - LOG_D(NR_RRC, "get SRB2_config from (ue_p->SRB_configList2[%d])\n", xid); + for (int i = 0; (i < (*SRB_configList2)->list.count) && (i < 3); i++) { + if ((*SRB_configList2)->list.array[i]->srb_Identity == 2) { + LOG_D(NR_RRC, "RRC Reestablishment - get SRB2_config from (ue_p->SRB_configList2[%d])\n", old_xid); SRB2_config = (*SRB_configList2)->list.array[i]; SRB2_config->reestablishPDCP = CALLOC(1, sizeof(*SRB2_config->reestablishPDCP)); *SRB2_config->reestablishPDCP = NR_SRB_ToAddMod__reestablishPDCP_true; @@ -1320,15 +1320,11 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx } } - // SRB2_config = CALLOC(1, sizeof(*SRB2_config)); - // SRB2_config->srb_Identity = 2; - SRB_configList2 = &(ue_p->SRB_configList2[new_xid]); - DRB_configList2 = &(ue_p->DRB_configList2[new_xid]); if (*SRB_configList2) { free(*SRB_configList2); - LOG_D(NR_RRC, "free(ue_p->SRB_configList2[%d])\n", new_xid); + LOG_D(NR_RRC, "RRC Reestablishment - free(ue_p->SRB_configList2[%d])\n", new_xid); } *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); @@ -1337,42 +1333,74 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx // Add SRB2 to SRB configuration list asn1cSeqAdd(&SRB_configList->list, SRB2_config); asn1cSeqAdd(&(*SRB_configList2)->list, SRB2_config); - LOG_D(NR_RRC, "Add SRB2_config (srb_Identity:%ld) to ue_p->SRB_configList\n", SRB2_config->srb_Identity); - LOG_D(NR_RRC, "Add SRB2_config (srb_Identity:%ld) to ue_p->SRB_configList2[%d]\n", SRB2_config->srb_Identity, new_xid); + LOG_D(NR_RRC, "RRC Reestablishment - Add SRB2_config (srb_Identity:%ld) to ue_p->SRB_configList\n", SRB2_config->srb_Identity); + LOG_D(NR_RRC, + "RRC Reestablishment - Add SRB2_config (srb_Identity:%ld) to ue_p->SRB_configList2[%d]\n", + SRB2_config->srb_Identity, + new_xid); } else { // SRB configuration list only contains SRB1. - LOG_W(NR_RRC,"SRB2 configuration does not exist in SRB configuration list\n"); - } - - if (*DRB_configList2) { - free(*DRB_configList2); - LOG_D(NR_RRC, "free(ue_p->DRB_configList2[%d])\n", new_xid); - } - - *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); - - if (DRB_configList != NULL) { - LOG_D(NR_RRC, "get DRB_config from (ue_p->DRB_configList)\n"); - - for (i = 0; (i < DRB_configList->list.count) && (i < 3); i++) { - DRB_config = DRB_configList->list.array[i]; - asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); - // Add DRB to DRB configuration list, for LTE_RRCConnectionReconfigurationComplete - asn1cSeqAdd(&(*DRB_configList2)->list, DRB_config); - } + LOG_W(NR_RRC, "RRC Reestablishment - SRB2 configuration does not exist in SRB configuration list\n"); } ue_p->Srb[1].Active = 1; if (get_softmodem_params()->sa) { - LOG_W(NR_RRC, "Rework identity mapping need to be done properly!\n"); - gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0}; + uint8_t send_security_mode_command = false; + nr_rrc_pdcp_config_security(ctxt_pP, ue_context_pP, send_security_mode_command); + LOG_D(NR_RRC, "RRC Reestablishment - set security successfully \n"); + } +} + +/// @brief Function used in RRCReestablishmentComplete procedure to reestablish the DRBs +/// that the UE previously had, it gets the information from the established_drbs +/// struct. +/// @param new_xid The new RRC transaction id. +void RRCReestablishmentComplete_fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP, + const uint8_t new_xid) +{ + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + NR_DRB_ToAddMod_t *DRB_config = NULL; + NR_DRB_ToAddModList_t **DRB_configList2 = &(ue_p->DRB_configList2[new_xid]); + + if (*DRB_configList2) { + free(*DRB_configList2); + LOG_D(NR_RRC, "RRC Reestablishment - free(ue_p->DRB_configList2[%d])\n", new_xid); + } + + *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); + + for (int i = 0; i < NGAP_MAX_DRBS_PER_UE; i++) { + if (ue_p->established_drbs[i].status != DRB_INACTIVE) { + ue_p->established_drbs[i].reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true; + DRB_config = generateDRB_ASN1(&ue_p->established_drbs[i]); + asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); + asn1cSeqAdd(&(*DRB_configList2)->list, DRB_config); + } + } +} + +/// @brief Function used in RRCReestablishmentComplete procedure to update the NGU Tunnels. +/// @param reestablish_rnti is the old C-RNTI +void RRCReestablishmentComplete_update_ngu_tunnel(const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP, + const rnti_t reestablish_rnti) +{ + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + int i = 0; + int j = 0; + int ret = 0; + + if (get_softmodem_params()->sa) { + LOG_W(NR_RRC, "RRC Reestablishment - Rework identity mapping need to be done properly!\n"); + gtpv1u_gnb_create_tunnel_req_t create_tunnel_req = {0}; /* Save e RAB information for later */ - int j; + for (j = 0, i = 0; i < NB_RB_MAX; i++) { if (ue_p->pduSession[i].status == PDU_SESSION_STATUS_ESTABLISHED || ue_p->pduSession[i].status == PDU_SESSION_STATUS_DONE) { create_tunnel_req.pdusession_id[j] = ue_p->pduSession[i].param.pdusession_id; - create_tunnel_req.incoming_rb_id[j] = i+1; + create_tunnel_req.incoming_rb_id[j] = i + 1; create_tunnel_req.outgoing_teid[j] = ue_p->pduSession[i].param.gtp_teid; // to be developped, use the first QFI only create_tunnel_req.outgoing_qfi[j] = ue_p->pduSession[i].param.qos[0].qfi; @@ -1383,14 +1411,11 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx } create_tunnel_req.ue_id = ctxt_pP->rntiMaybeUEid; // warning put zero above - create_tunnel_req.num_tunnels = j; - ret = gtpv1u_update_ngu_tunnel( - ctxt_pP->instance, - &create_tunnel_req, - reestablish_rnti); + create_tunnel_req.num_tunnels = j; + ret = gtpv1u_update_ngu_tunnel(ctxt_pP->instance, &create_tunnel_req, reestablish_rnti); - if ( ret != 0 ) { - LOG_E(NR_RRC, "gtpv1u_update_ngu_tunnel failed,start to release UE %x\n", reestablish_rnti); + if (ret != 0) { + LOG_E(NR_RRC, "RRC Reestablishment - gtpv1u_update_ngu_tunnel failed,start to release UE %x\n", reestablish_rnti); ue_p->ue_release_timer_s1 = 1; ue_p->ue_release_timer_thres_s1 = 100; ue_p->ue_release_timer = 0; @@ -1400,34 +1425,72 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx return; } } +} + +/// @brief Function used in RRCReestablishmentComplete procedure to update the NAS PDUSessions and the xid. +/// @param old_xid Refers to the old transaction identifier passed to rrc_gNB_process_RRCReestablishmentComplete as xid. +/// @todo parameters yet to process inside the for loop. +/// @todo should test if pdu session are Ok before! inside the for loop. +void RRCReestablishmentComplete_nas_pdu_update(rrc_gNB_ue_context_t *ue_context_pP, const uint8_t old_xid) +{ + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + /* Add all NAS PDUs to the list */ + for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { + ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE; + ue_p->pduSession[i].xid = old_xid; + LOG_D(NR_RRC, + "RRC Reestablishment - setting the status for the default DRB (index %d) to (%d,%s)\n", + i, + ue_p->pduSession[i].status, + "PDU_SESSION_STATUS_DONE"); + } +} + +/// @brief Function used in RRCReestablishmentComplete procedure to Free all the NAS PDU buffers. +void RRCReestablishmentComplete_nas_pdu_free(rrc_gNB_ue_context_t *ue_context_pP) +{ + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + /* Free all NAS PDUs */ + for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { + if (ue_p->pduSession[i].param.nas_pdu.buffer != NULL) { + /* Free the NAS PDU buffer and invalidate it */ + free(ue_p->pduSession[i].param.nas_pdu.buffer); + ue_p->pduSession[i].param.nas_pdu.buffer = NULL; + } + } +} + +/// @brief Function tha processes RRCReestablishmentComplete message sent by the UE, after RRCReestasblishment request. +/// @param ctxt_pP Protocol context containing information regarding the UE and gNB +/// @param reestablish_rnti is the old C-RNTI +/// @param ue_context_pP UE context container information regarding the UE +/// @param xid Transaction Identifier used in RRC messages +void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctxt_pP, + const rnti_t reestablish_rnti, + rrc_gNB_ue_context_t *ue_context_pP, + const uint8_t xid) +{ + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + LOG_I(NR_RRC, + "[RAPROC] UE %04x Logical Channel UL-DCCH, processing NR_RRCReestablishmentComplete from UE (SRB1 Active)\n", + ue_p->rnti); + + int i = 0; + + uint8_t new_xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); + ue_p->StatusRrc = NR_RRC_CONNECTED; + ue_p->ue_rrc_inactivity_timer = 1; // set rrc inactivity when UE goes into RRC_CONNECTED + ue_p->reestablishment_xid = new_xid; + + RRCReestablishmentComplete_fill_SRB2_configList(ctxt_pP, ue_context_pP, xid, new_xid); + RRCReestablishmentComplete_fill_DRB_configList(ctxt_pP, ue_context_pP, new_xid); + RRCReestablishmentComplete_update_ngu_tunnel(ctxt_pP, ue_context_pP, reestablish_rnti); + RRCReestablishmentComplete_nas_pdu_update(ue_context_pP, xid); /* Update RNTI in ue_context */ - LOG_I(NR_RRC, "Updating UEid from %04x to %lx\n", ue_p->rnti, ctxt_pP->rntiMaybeUEid); + LOG_I(NR_RRC, "RRC Reestablishment - Updating UEid from %04x to %lx\n", ue_p->rnti, ctxt_pP->rntiMaybeUEid); rrc_gNB_update_ue_context_rnti(ctxt_pP->rntiMaybeUEid, RC.nrrrc[ctxt_pP->module_id], ue_p->gNB_ue_ngap_id); - if (get_softmodem_params()->sa) { - uint8_t send_security_mode_command = false; - nr_rrc_pdcp_config_security( - ctxt_pP, - ue_context_pP, - send_security_mode_command ? 0 : 1); - LOG_D(NR_RRC, "set security successfully \n"); - } - - uint8_t drb_id_to_setup_start = DRB_configList ? DRB_configList->list.array[0]->drb_Identity : 1; - uint8_t nb_drb_to_setup = DRB_configList ? DRB_configList->list.count : ue_p->nb_of_pdusessions; - /* TODO: hardcoded to 13 for the time being, to be changed? */ - long drb_priority[NGAP_MAX_DRBS_PER_UE] = {13}; - - /* Add all NAS PDUs to the list */ - for (i = 0; i < ue_p->nb_of_pdusessions; i++) { - /* TODO parameters yet to process ... */ - /* TODO should test if pdu session are Ok before! */ - ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE; - ue_p->pduSession[i].xid = xid; - LOG_D(NR_RRC, "setting the status for the default DRB (index %d) to (%d,%s)\n", i, ue_p->pduSession[i].status, "PDU_SESSION_STATUS_DONE"); - } - gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; NR_CellGroupConfig_t *cellGroupConfig = calloc(1, sizeof(NR_CellGroupConfig_t)); @@ -1435,51 +1498,62 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx ue_p->masterCellGroup->spCellConfig = ue_p->spCellConfigReestablishment; ue_p->spCellConfigReestablishment = NULL; cellGroupConfig->spCellConfig = ue_p->masterCellGroup->spCellConfig; -cellGroupConfig->physicalCellGroupConfig = ue_p->masterCellGroup->physicalCellGroupConfig; + cellGroupConfig->physicalCellGroupConfig = ue_p->masterCellGroup->physicalCellGroupConfig; - fill_mastercellGroupConfig(cellGroupConfig, ue_p->masterCellGroup, rrc->um_on_default_drb, (drb_id_to_setup_start < 2) ? 1 : 0, drb_id_to_setup_start, nb_drb_to_setup, drb_priority); + uint8_t drb_id_to_setup_start = ue_p->DRB_configList ? ue_p->DRB_configList->list.array[0]->drb_Identity : 1; + uint8_t nb_drb_to_setup = ue_p->DRB_configList ? ue_p->DRB_configList->list.count : ue_p->nb_of_pdusessions; + /* TODO: hardcoded to 13 for the time being, to be changed? */ + long drb_priority[NGAP_MAX_DRBS_PER_UE] = {13}; - for(i = 0; i < cellGroupConfig->rlc_BearerToAddModList->list.count; i++) { - cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC = CALLOC(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC)); + fill_mastercellGroupConfig(cellGroupConfig, + ue_p->masterCellGroup, + rrc->um_on_default_drb, + (drb_id_to_setup_start < 2) ? 1 : 0, + drb_id_to_setup_start, + nb_drb_to_setup, + drb_priority); + + for (i = 0; i < cellGroupConfig->rlc_BearerToAddModList->list.count; i++) { + cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC = + CALLOC(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC)); *cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC = NR_RLC_BearerConfig__reestablishRLC_true; } uint8_t buffer[RRC_BUF_SIZE] = {0}; int size = do_RRCReconfiguration(ctxt_pP, - buffer, - RRC_BUF_SIZE, - new_xid, - *SRB_configList2, - DRB_configList, - NULL, - NULL, - NULL, - NULL, // MeasObj_list, - NULL, - ue_context_pP, - &rrc->carrier, - NULL, - NULL, - cellGroupConfig); + buffer, + RRC_BUF_SIZE, + new_xid, + ue_p->SRB_configList2[new_xid], + ue_p->DRB_configList2[new_xid], + NULL, + NULL, + NULL, + NULL, // MeasObj_list, + NULL, + ue_context_pP, + &rrc->carrier, + NULL, + NULL, + cellGroupConfig); - LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size, "[MSG] RRC Reconfiguration\n"); + LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buffer, size, "[MSG] RRC Reconfiguration\n"); - /* Free all NAS PDUs */ - for (i = 0; i < ue_p->nb_of_pdusessions; i++) { - if (ue_p->pduSession[i].param.nas_pdu.buffer != NULL) { - /* Free the NAS PDU buffer and invalidate it */ - free(ue_p->pduSession[i].param.nas_pdu.buffer); - ue_p->pduSession[i].param.nas_pdu.buffer = NULL; - } - } + RRCReestablishmentComplete_nas_pdu_free(ue_context_pP); if (size < 0) { LOG_E(NR_RRC, "RRC decode err!!! do_RRCReconfiguration\n"); return; } else { - LOG_I(NR_RRC, "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate NR_RRCReconfiguration (bytes %d, UE id %04x)\n", ctxt_pP->module_id, ctxt_pP->frame, size, ue_p->rnti); + LOG_I(NR_RRC, + "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate NR_RRCReconfiguration (bytes %d, UE id %04x)\n", + ctxt_pP->module_id, + ctxt_pP->frame, + size, + ue_p->rnti); LOG_D(NR_RRC, - "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (RRCReconfiguration to UE %04x MUI %d) --->][PDCP][MOD %u][RB %u]\n", + "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (RRCReconfiguration to UE %04x MUI %d) --->][PDCP][MOD " + "%u][RB %u]\n", ctxt_pP->frame, ctxt_pP->module_id, size, @@ -1493,12 +1567,16 @@ cellGroupConfig->physicalCellGroupConfig = ue_p->masterCellGroup->physicalCellGr } if (NODE_IS_DU(RC.nrrrc[ctxt_pP->module_id]->node_type) || NODE_IS_MONOLITHIC(RC.nrrrc[ctxt_pP->module_id]->node_type)) { - uint32_t delay_ms = ue_p->masterCellGroup && ue_p->masterCellGroup->spCellConfig && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated + uint32_t delay_ms = ue_p->masterCellGroup && ue_p->masterCellGroup->spCellConfig + && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList ? NR_RRC_RECONFIGURATION_DELAY_MS + NR_RRC_BWP_SWITCHING_DELAY_MS : NR_RRC_RECONFIGURATION_DELAY_MS; - nr_mac_enable_ue_rrc_processing_timer(ctxt_pP->module_id, ue_p->rnti, *RC.nrrrc[ctxt_pP->module_id]->carrier.servingcellconfigcommon->ssbSubcarrierSpacing, delay_ms); + nr_mac_enable_ue_rrc_processing_timer(ctxt_pP->module_id, + ue_p->rnti, + *RC.nrrrc[ctxt_pP->module_id]->carrier.servingcellconfigcommon->ssbSubcarrierSpacing, + delay_ms); } } //----------------------------------------------------------------------------- diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 1848601de8..b4d6c55762 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -36,65 +36,109 @@ rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create) return ue->pduSession + j; } -NR_DRB_ToAddMod_t *generateDRB(gNB_RRC_UE_t *ue, uint8_t drb_id, rrc_pdu_session_param_t *pduSession, bool enable_sdap, int do_drb_integrity, int do_drb_ciphering) +void generateDRB(gNB_RRC_UE_t *ue, + uint8_t drb_id, + rrc_pdu_session_param_t *pduSession, + bool enable_sdap, + int do_drb_integrity, + int do_drb_ciphering) +{ + int i; + int qos_flow_index; + drb_t *est_drb = &ue->established_drbs[drb_id - 1]; + if (est_drb->status == DRB_INACTIVE) { + /* DRB Management */ + est_drb->drb_id = drb_id; + est_drb->reestablishPDCP = -1; + est_drb->recoverPDCP = -1; + for (i = 0; i < NGAP_MAX_DRBS_PER_UE; i++) { + if ((est_drb->cnAssociation.sdap_config.pdusession_id == 0 + || est_drb->cnAssociation.sdap_config.pdusession_id == pduSession->param.pdusession_id) + && est_drb->defaultDRBid == 0) { + est_drb->cnAssociation.sdap_config.defaultDRB = true; + est_drb->defaultDRBid = drb_id; + } + } + /* SDAP Configuration */ + est_drb->cnAssociation.present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; + est_drb->cnAssociation.sdap_config.pdusession_id = pduSession->param.pdusession_id; + if (enable_sdap) { + est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_present; + est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_present; + } else { + est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_absent; + est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_absent; + } + for (qos_flow_index = 0; qos_flow_index < pduSession->param.nb_qos; qos_flow_index++) { + est_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] = pduSession->param.qos[qos_flow_index].qfi; + if (pduSession->param.qos[qos_flow_index].fiveQI > 5) + est_drb->status = DRB_ACTIVE_NONGBR; + else + est_drb->status = DRB_ACTIVE; + } + /* PDCP Configuration */ + est_drb->pdcp_config.discardTimer = NR_PDCP_Config__drb__discardTimer_infinity; + est_drb->pdcp_config.pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits; + est_drb->pdcp_config.pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; + est_drb->pdcp_config.t_Reordering = NR_PDCP_Config__t_Reordering_ms100; + est_drb->pdcp_config.headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; + est_drb->pdcp_config.headerCompression.NotUsed = 0; + if (do_drb_integrity) + est_drb->pdcp_config.integrityProtection = NR_PDCP_Config__drb__integrityProtection_enabled; + else + est_drb->pdcp_config.integrityProtection = 1; + if (do_drb_ciphering) + est_drb->pdcp_config.ext1.cipheringDisabled = 1; + else + est_drb->pdcp_config.ext1.cipheringDisabled = NR_PDCP_Config__ext1__cipheringDisabled_true; + } +} + +NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1) { NR_DRB_ToAddMod_t *DRB_config = CALLOC(1, sizeof(*DRB_config)); - DRB_config->drb_Identity = drb_id; + NR_SDAP_Config_t *SDAP_config = CALLOC(1, sizeof(NR_SDAP_Config_t)); + asn1cCalloc(DRB_config->cnAssociation, association); - association->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; + asn1cCalloc(SDAP_config->mappedQoS_FlowsToAdd, sdapFlows); + asn1cCalloc(DRB_config->pdcp_Config, pdcpConfig); + asn1cCalloc(pdcpConfig->drb, drb); + + DRB_config->drb_Identity = drb_asn1->drb_id; + association->present = drb_asn1->cnAssociation.present; /* SDAP Configuration */ - NR_SDAP_Config_t *SDAP_config = CALLOC(1, sizeof(NR_SDAP_Config_t)); - asn1cCalloc(SDAP_config->mappedQoS_FlowsToAdd, sdapFlows); + SDAP_config->pdu_Session = drb_asn1->cnAssociation.sdap_config.pdusession_id; + SDAP_config->sdap_HeaderDL = drb_asn1->cnAssociation.sdap_config.sdap_HeaderDL; + SDAP_config->sdap_HeaderUL = drb_asn1->cnAssociation.sdap_config.sdap_HeaderUL; + SDAP_config->defaultDRB = drb_asn1->cnAssociation.sdap_config.defaultDRB; - SDAP_config->pdu_Session = pduSession->param.pdusession_id; - - if (enable_sdap) { - SDAP_config->sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_present; - SDAP_config->sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_present; - } else { - SDAP_config->sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_absent; - SDAP_config->sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_absent; - } - - SDAP_config->defaultDRB = true; - - for (int qos_flow_index = 0; qos_flow_index < pduSession->param.nb_qos; qos_flow_index++) - { - asn1cSequenceAdd(sdapFlows->list, NR_QFI_t, qfi); - *qfi = pduSession->param.qos[qos_flow_index].qfi; - if(pduSession->param.qos[qos_flow_index].fiveQI > 5) - pduSession->param.used_drbs[drb_id - 1] = DRB_ACTIVE_NONGBR; - else - pduSession->param.used_drbs[drb_id - 1] = DRB_ACTIVE; + for (int qos_flow_index = 0; qos_flow_index < QOSFLOW_MAX_VALUE; qos_flow_index++) { + if (drb_asn1->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] != 0) { + asn1cSequenceAdd(sdapFlows->list, NR_QFI_t, qfi); + *qfi = drb_asn1->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index]; + } } association->choice.sdap_Config = SDAP_config; /* PDCP Configuration */ - asn1cCalloc(DRB_config->pdcp_Config, pdcpConfig); - asn1cCalloc(pdcpConfig->drb, drb); + asn1cCallocOne(drb->discardTimer, drb_asn1->pdcp_config.discardTimer); + asn1cCallocOne(drb->pdcp_SN_SizeUL, drb_asn1->pdcp_config.pdcp_SN_SizeUL); + asn1cCallocOne(drb->pdcp_SN_SizeDL, drb_asn1->pdcp_config.pdcp_SN_SizeDL); + asn1cCallocOne(pdcpConfig->t_Reordering, drb_asn1->pdcp_config.t_Reordering); - asn1cCallocOne(drb->discardTimer, NR_PDCP_Config__drb__discardTimer_infinity); + drb->headerCompression.present = drb_asn1->pdcp_config.headerCompression.present; + drb->headerCompression.choice.notUsed = drb_asn1->pdcp_config.headerCompression.NotUsed; - asn1cCallocOne(drb->pdcp_SN_SizeUL, NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits); - asn1cCallocOne(drb->pdcp_SN_SizeDL, NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits); - - drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; - drb->headerCompression.choice.notUsed = 0; - - asn1cCallocOne(pdcpConfig->t_Reordering, NR_PDCP_Config__t_Reordering_ms100); - - if (do_drb_integrity) { - asn1cCallocOne(drb->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled); + if (!drb_asn1->pdcp_config.integrityProtection) { + asn1cCallocOne(drb->integrityProtection, drb_asn1->pdcp_config.integrityProtection); } - if (!do_drb_ciphering) { + if (!drb_asn1->pdcp_config.ext1.cipheringDisabled) { asn1cCalloc(pdcpConfig->ext1, ext1); - asn1cCallocOne(ext1->cipheringDisabled, NR_PDCP_Config__ext1__cipheringDisabled_true); + asn1cCallocOne(ext1->cipheringDisabled, drb_asn1->pdcp_config.ext1.cipheringDisabled); } - ue->DRB_active[drb_id-1] = DRB_ACTIVE; - return DRB_config; } diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.h b/openair2/RRC/NR/rrc_gNB_radio_bearers.h index 62065c1d87..219bc21948 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.h +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.h @@ -35,7 +35,24 @@ #define GBR_FLOW (1) #define NONGBR_FLOW (0) -NR_DRB_ToAddMod_t *generateDRB(gNB_RRC_UE_t *rrc_ue, uint8_t drb_id, rrc_pdu_session_param_t *pduSession, bool enable_sdap, int do_drb_integrity, int do_drb_ciphering); +/// @brief Generates an ASN1 DRB-ToAddMod, from the established_drbs in gNB_RRC_UE_t. +/// @param drb_t drb_asn1 +/// @return Returns the ASN1 DRB-ToAddMod structs. +NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1); +/// @brief Creates and stores a DRB in the gNB_RRC_UE_t struct, it doesn't create the actual entity, +/// to create the actual entity use the generateDRB_ASN1. +/// @param ue The gNB_RRC_UE_t struct that holds information for the UEs +/// @param drb_id The Data Radio Bearer Identity to be created for the established DRB. +/// @param pduSession The PDU Session that the DRB is created for. +/// @param enable_sdap If true the SDAP header will be added to the packet, else it will not add or search for SDAP header. +/// @param do_drb_integrity +/// @param do_drb_ciphering +void generateDRB(gNB_RRC_UE_t *ue, + uint8_t drb_id, + rrc_pdu_session_param_t *pduSession, + bool enable_sdap, + int do_drb_integrity, + int do_drb_ciphering); uint8_t next_available_drb(gNB_RRC_UE_t *ue, rrc_pdu_session_param_t *pdusession, bool is_gbr); bool drb_is_active(gNB_RRC_UE_t *ue, uint8_t drb_id); diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.c b/openair3/NAS/NR_UE/nr_nas_msg_sim.c index e411c53994..e20a0fc99e 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg_sim.c +++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.c @@ -622,7 +622,7 @@ static void decodeRegistrationAccept(uint8_t *buf, int len, nr_ue_nas_t *nas) 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)); + 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 */