diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 0fb4824d42..465679d002 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -724,3 +724,4 @@ void SLIV2SL(int SLIV,int *S,int *L) { *S=13-SLIVmod14; } } + diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 946e06dd62..893dcba701 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -56,10 +56,9 @@ typedef enum frequency_range_e { } frequency_range_t; extern const nr_bandentry_t nr_bandtable[]; + static inline int get_num_dmrs(uint16_t dmrs_mask ) { - int num_dmrs=0; - for (int i=0;i<16;i++) num_dmrs+=((dmrs_mask>>i)&1); return(num_dmrs); } diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index 75a7ac67b1..205e107bf9 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -777,6 +777,7 @@ typedef struct { } nfapi_nr_dl_tti_pdcch_pdu_rel15_t; typedef struct { + uint8_t ldpcBaseGraph; uint32_t tbSizeLbrmBytes; }nfapi_v3_pdsch_maintenance_parameters_t; @@ -1193,6 +1194,7 @@ typedef struct #define PUSCH_PDU_BITMAP_DFTS_OFDM 0x8 typedef struct { + uint8_t ldpcBaseGraph; uint32_t tbSizeLbrmBytes; }nfapi_v3_pusch_maintenance_parameters_t; diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index af00abddc5..be2afed94d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -375,14 +375,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc } - // target_code_rate is in 0.1 units - float Coderate = (float) rel15->targetCodeRate[0] / 10240.0f; - LOG_D(PHY,"DLSCH Coderate %f\n",Coderate); - - if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25) - impp.BG = 2; - else - impp.BG = 1; + impp.BG = rel15->maintenance_parms_v3.ldpcBaseGraph; start_meas(dlsch_segmentation_stats); impp.Kb = nr_segmentation(harq->b, harq->c, harq->B, &impp.n_segments, &impp.K, impp.Zc, &impp.F, impp.BG); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index aa007790a1..e9038f25d8 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -380,7 +380,6 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, uint32_t r; uint32_t r_offset; uint32_t offset; - int kc; int E; int8_t llrProcBuf[22*384]; int ret = 0; @@ -462,8 +461,9 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, LOG_D(PHY,"ULSCH Decoding, harq_pid %d TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, Coderate %f RV %d round %d\n", harq_pid, A, G, mcs, n_layers, nb_rb, Qm, Coderate, pusch_pdu->pusch_data.rv_index, harq_process->round); - if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){ - p_decParams->BG = 2; + p_decParams->BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph; + int kc; + if (p_decParams->BG == 2){ kc = 52; if (Coderate < 0.3333) { p_decParams->R = 15; @@ -475,7 +475,6 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, p_decParams->R = 23; } } else { - p_decParams->BG = 1; kc = 68; if (Coderate < 0.6667) { p_decParams->R = 13; diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index 498efa28d9..f429409d5a 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -84,45 +84,45 @@ nrUE_params_t *get_nrUE_params(void) { int main(int argc, char **argv) { - char c; - int i; //,j,l,aa; - double SNR, SNR_lin, snr0 = -2.0, snr1 = 2.0; - double snr_step = 0.1; - uint8_t snr1set = 0; - int **txdata; - double **s_re, **s_im, **r_re, **r_im; - // int sync_pos, sync_pos_slot; - // FILE *rx_frame_file; - FILE *output_fd = NULL; - //uint8_t write_output_file = 0; - // int subframe_offset; - // char fname[40], vname[40]; - int trial, n_trials = 1, n_errors = 0, n_false_positive = 0; - uint8_t n_tx = 1, n_rx = 1; - //uint8_t transmission_mode = 1; - uint16_t Nid_cell = 0; - channel_desc_t *gNB2UE; - uint8_t extended_prefix_flag = 0; - //int8_t interf1 = -21, interf2 = -21; - FILE *input_fd = NULL, *pbch_file_fd = NULL; - //char input_val_str[50],input_val_str2[50]; - //uint16_t NB_RB=25; - SCM_t channel_model = AWGN; //Rayleigh1_anticorr; - uint16_t N_RB_DL = 106, mu = 1; - //unsigned char frame_type = 0; - unsigned char pbch_phase = 0; - int frame = 0, slot = 0; - int frame_length_complex_samples; - //int frame_length_complex_samples_no_prefix; - NR_DL_FRAME_PARMS *frame_parms; - uint8_t Kmimo = 0; - uint32_t Nsoft = 0; - double sigma; - unsigned char qbits = 8; - int ret; - //int run_initial_sync=0; - int loglvl = OAILOG_WARNING; - uint8_t dlsch_threads = 0; + char c; + int i; //,j,l,aa; + double SNR, SNR_lin, snr0 = -2.0, snr1 = 2.0; + double snr_step = 0.1; + uint8_t snr1set = 0; + int **txdata; + double **s_re, **s_im, **r_re, **r_im; + // int sync_pos, sync_pos_slot; + // FILE *rx_frame_file; + FILE *output_fd = NULL; + //uint8_t write_output_file = 0; + // int subframe_offset; + // char fname[40], vname[40]; + int trial, n_trials = 1, n_errors = 0, n_false_positive = 0; + uint8_t n_tx = 1, n_rx = 1; + //uint8_t transmission_mode = 1; + uint16_t Nid_cell = 0; + channel_desc_t *gNB2UE; + uint8_t extended_prefix_flag = 0; + //int8_t interf1 = -21, interf2 = -21; + FILE *input_fd = NULL, *pbch_file_fd = NULL; + //char input_val_str[50],input_val_str2[50]; + //uint16_t NB_RB=25; + SCM_t channel_model = AWGN; //Rayleigh1_anticorr; + uint16_t N_RB_DL = 106, mu = 1; + //unsigned char frame_type = 0; + unsigned char pbch_phase = 0; + int frame = 0, slot = 0; + int frame_length_complex_samples; + //int frame_length_complex_samples_no_prefix; + NR_DL_FRAME_PARMS *frame_parms; + uint8_t Kmimo = 0; + uint32_t Nsoft = 0; + double sigma; + unsigned char qbits = 8; + int ret; + //int run_initial_sync=0; + int loglvl = OAILOG_WARNING; + uint8_t dlsch_threads = 0; float target_error_rate = 0.01; uint64_t SSB_positions=0x01; uint16_t nb_symb_sch = 12; @@ -468,6 +468,7 @@ int main(int argc, char **argv) rel15->mcsIndex[0] = Imcs; rel15->numDmrsCdmGrpsNoData = 1; rel15->maintenance_parms_v3.tbSizeLbrmBytes = Tbslbrm; + rel15->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS, rate); double modulated_input[16 * 68 * 384]; // [hna] 16 segments, 68*Zc short channel_output_fixed[16 * 68 * 384]; //unsigned char *estimated_output; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 7e141fae57..51e9f448ae 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -327,6 +327,7 @@ void nr_dlsim_preprocessor(module_id_t module_id, sched_pdsch->rbStart = g_rbStart; sched_pdsch->rbSize = g_rbSize; sched_pdsch->mcs = g_mcsIndex; + sched_pdsch->nrOfLayers = g_nrOfLayers; /* the following might override the table that is mandated by RRC * configuration */ current_BWP->mcsTableIdx = g_mcsTableIdx; diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index da0cc7bc80..6ef8bff116 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -472,6 +472,7 @@ int main(int argc, char **argv) rel15_ul->nrOfLayers = Nl; rel15_ul->target_code_rate = code_rate; rel15_ul->pusch_data.tb_size = TBS>>3; + rel15_ul->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS, code_rate); /////////////////////////////////////////////////// double modulated_input[16 * 68 * 384]; // [hna] 16 segments, 68*Zc diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 087b3be6a8..43ac3fc145 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -1135,7 +1135,7 @@ int main(int argc, char **argv) pusch_pdu->bwp_size = abwp_size; } - pusch_pdu->pusch_data.tb_size = TBS/8; + pusch_pdu->pusch_data.tb_size = TBS>>3; pusch_pdu->pdu_bit_map = pdu_bit_map; pusch_pdu->rnti = n_rnti; pusch_pdu->mcs_index = Imcs; @@ -1168,6 +1168,7 @@ int main(int argc, char **argv) pusch_pdu->pusch_ptrs.ptrs_freq_density = ptrs_freq_density; pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t)); pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; + pusch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS, code_rate); // if transform precoding is enabled if (transform_precoding == transformPrecoder_enabled) { diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 379823fc6a..8a66c5d879 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -3498,6 +3498,15 @@ void csi_period_offset(NR_CSI_ReportConfig_t *csirep, } } +uint8_t get_BG(uint32_t A, uint16_t R) { + + float code_rate = (float) R / 10240.0f; + if ((A <=292) || ((A<=3824) && (code_rate <= 0.6667)) || code_rate <= 0.25) + return 2; + else + return 1; +} + uint32_t get_Y(NR_SearchSpace_t *ss, int slot, rnti_t rnti) { if(ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 294c306fd0..d45c01b4b0 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -40,6 +40,8 @@ uint32_t get_Y(NR_SearchSpace_t *ss, int slot, rnti_t rnti); +uint8_t get_BG(uint32_t A, uint16_t R); + uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t dl_nrarfcn); uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, uint32_t bw); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 5d4b3e7cd3..f2bfd9fce1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1057,6 +1057,8 @@ void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, pusch_pdu->mcs_index = mcsindex; pusch_pdu->pusch_data.tb_size = TBS; + pusch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS<<3,R); + } } @@ -1322,6 +1324,7 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra pdsch_pdu_rel15->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(mcsTableIdx, bw_tbslbrm, 1); + pdsch_pdu_rel15->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS<<3,R); // Fill PDCCH DL DCI PDU nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; @@ -1703,6 +1706,7 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra pdsch_pdu_rel15->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(mcsTableIdx, bw_tbslbrm, 1); + pdsch_pdu_rel15->maintenance_parms_v3.ldpcBaseGraph = get_BG(harq->tb_size<<3,R); pdsch_pdu_rel15->precodingAndBeamforming.num_prgs=1; pdsch_pdu_rel15->precodingAndBeamforming.prg_size=275; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 90d0af946a..cf05491a10 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -465,6 +465,7 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, pdsch_pdu_rel15->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(0, pdsch_pdu_rel15->BWPSize, 1); + pdsch_pdu_rel15->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS<<3,pdsch_pdu_rel15->targetCodeRate[0]); /* Fill PDCCH DL DCI PDU */ nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index fcfdff53dd..597477c3d3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -1071,6 +1071,7 @@ void nr_schedule_ue_spec(module_id_t module_id, pdsch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(current_BWP->mcsTableIdx, bw_tbslbrm, nl_tbslbrm); + pdsch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS<<3,R); NR_PDSCH_Config_t *pdsch_Config = current_BWP->pdsch_Config; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 348422749a..e991c2450a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -214,6 +214,7 @@ uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx) return 9; } + void set_dl_dmrs_ports(NR_pdsch_semi_static_t *ps) { //TODO first basic implementation of dmrs port selection diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 7ac53509f7..082e8dc599 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -53,6 +53,32 @@ const int get_ul_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon return 0; // if FDD or not mixed slot in TDD, for now use default TDA (TODO handle CSI-RS slots) } +int compute_bw_factor(int mu, int rb) { + // 38.213 7.1.1 + return (10 * log10(rb << mu)); +} + +int compute_delta_tf(int tbs_bits, + int rb, + int n_layers, + int n_symbols, + int n_dmrs, + long *deltaMCS) { + + // 38.213 7.1.1 + // if the PUSCH transmission is over more than one layer delta_tf = 0 + if(deltaMCS == NULL || n_layers>1) + return 0; + else + AssertFatal(1==0,"Compute DeltaTF not yet fully supported\n"); + + const int n_re = (NR_NB_SC_PER_RB * n_symbols - n_dmrs) * rb; + const int BPRE = tbs_bits/n_re; //TODO change for PUSCH with CSI + const float f = pow(2, (float) BPRE * 1.25); + const float beta = 1.0f; //TODO change for PUSCH with CSI + return(10 * log10((f - 1) * beta)); +} + // For both UL-SCH except: // - UL-SCH: fixed-size MAC CE(known by LCID) // - UL-SCH: padding @@ -77,320 +103,321 @@ const int get_ul_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon // F: length of L is 0:8 or 1:16 bits wide // R: Reserved bit, set to zero. -int nr_process_mac_pdu( instance_t module_idP, - NR_UE_info_t* UE, - uint8_t CC_id, - frame_t frameP, - sub_frame_t slot, - uint8_t *pduP, - int pdu_len) +int nr_process_mac_pdu(instance_t module_idP, + NR_UE_info_t* UE, + uint8_t CC_id, + frame_t frameP, + sub_frame_t slot, + uint8_t *pduP, + int pdu_len, + const int8_t harq_pid) { + uint8_t done = 0; - uint8_t done = 0; - int sdus = 0; + int sdus = 0; + NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + if (pduP[0] != UL_SCH_LCID_PADDING) + trace_NRpdu(DIRECTION_UPLINK, pduP, pdu_len, WS_C_RNTI, UE->rnti, frameP, 0, 0, 0); - if ( pduP[0] != UL_SCH_LCID_PADDING ) - trace_NRpdu(DIRECTION_UPLINK, pduP, pdu_len, WS_C_RNTI, UE->rnti, frameP, 0, 0, 0); +#ifdef ENABLE_MAC_PAYLOAD_DEBUG + LOG_I(NR_MAC, "In %s: dumping MAC PDU in %d.%d:\n", __func__, frameP, slot); + log_dump(NR_MAC, pduP, pdu_len, LOG_DUMP_CHAR, "\n"); +#endif - #ifdef ENABLE_MAC_PAYLOAD_DEBUG - LOG_I(NR_MAC, "In %s: dumping MAC PDU in %d.%d:\n", __func__, frameP, slot); - log_dump(NR_MAC, pduP, pdu_len, LOG_DUMP_CHAR, "\n"); - #endif + while (!done && pdu_len > 0){ + uint16_t mac_len=0; + uint16_t mac_subheader_len=sizeof(NR_MAC_SUBHEADER_FIXED); + uint8_t rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID; - while (!done && pdu_len > 0){ - uint16_t mac_len=0; - uint16_t mac_subheader_len=sizeof(NR_MAC_SUBHEADER_FIXED); - uint8_t rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID; + LOG_D(NR_MAC, "In %s: received UL-SCH sub-PDU with LCID 0x%x in %d.%d (remaining PDU length %d)\n", __func__, rx_lcid, frameP, slot, pdu_len); - LOG_D(NR_MAC, "In %s: received UL-SCH sub-PDU with LCID 0x%x in %d.%d (remaining PDU length %d)\n", __func__, rx_lcid, frameP, slot, pdu_len); + unsigned char *ce_ptr; + int n_Lcg = 0; - unsigned char *ce_ptr; - int n_Lcg = 0; - - switch(rx_lcid){ - // MAC CE - - /*#ifdef DEBUG_HEADER_PARSING - LOG_D(NR_MAC, "[UE] LCID %d, PDU length %d\n", ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID, pdu_len); - #endif*/ - case UL_SCH_LCID_RECOMMENDED_BITRATE_QUERY: - // 38.321 Ch6.1.3.20 - mac_len = 2; - break; - case UL_SCH_LCID_CONFIGURED_GRANT_CONFIRMATION: - // 38.321 Ch6.1.3.7 - break; - - case UL_SCH_LCID_S_BSR: - case UL_SCH_LCID_S_TRUNCATED_BSR: - //38.321 section 6.1.3.1 - //fixed length - mac_len =1; - /* Extract short BSR value */ - ce_ptr = &pduP[mac_subheader_len]; - NR_BSR_SHORT *bsr_s = (NR_BSR_SHORT *) ce_ptr; - sched_ctrl->estimated_ul_buffer = 0; - sched_ctrl->estimated_ul_buffer = NR_SHORT_BSR_TABLE[bsr_s->Buffer_size]; - LOG_D(NR_MAC, - "SHORT BSR at %4d.%2d, LCG ID %d, BS Index %d, BS value < %d, est buf %d\n", - frameP, - slot, - bsr_s->LcgID, - bsr_s->Buffer_size, - NR_SHORT_BSR_TABLE[bsr_s->Buffer_size], - sched_ctrl->estimated_ul_buffer); - break; - - case UL_SCH_LCID_L_BSR: - case UL_SCH_LCID_L_TRUNCATED_BSR: - //38.321 section 6.1.3.1 - //variable length - /* Several checks have been added to this function to - ensure that the casting of the pduP is possible. There seems - to be a partial PDU at the end of this buffer, so here - we gracefully ignore that by returning 0. See: - https://gitlab.eurecom.fr/oai/openairinterface5g/-/issues/534 */ - if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) - return 0; - /* Extract long BSR value */ - ce_ptr = &pduP[mac_subheader_len]; - NR_BSR_LONG *bsr_l = (NR_BSR_LONG *) ce_ptr; - sched_ctrl->estimated_ul_buffer = 0; - - n_Lcg = bsr_l->LcgID7 + bsr_l->LcgID6 + bsr_l->LcgID5 + bsr_l->LcgID4 + - bsr_l->LcgID3 + bsr_l->LcgID2 + bsr_l->LcgID1 + bsr_l->LcgID0; - - LOG_D(NR_MAC, "LONG BSR, LCG ID(7-0) %d/%d/%d/%d/%d/%d/%d/%d\n", - bsr_l->LcgID7, bsr_l->LcgID6, bsr_l->LcgID5, bsr_l->LcgID4, - bsr_l->LcgID3, bsr_l->LcgID2, bsr_l->LcgID1, bsr_l->LcgID0); - - for (int n = 0; n < n_Lcg; n++){ - LOG_D(NR_MAC, "LONG BSR, %d/%d (n/n_Lcg), BS Index %d, BS value < %d", - n, n_Lcg, pduP[mac_subheader_len + 1 + n], - NR_LONG_BSR_TABLE[pduP[mac_subheader_len + 1 + n]]); - sched_ctrl->estimated_ul_buffer += - NR_LONG_BSR_TABLE[pduP[mac_subheader_len + 1 + n]]; - LOG_D(NR_MAC, - "LONG BSR at %4d.%2d, %d/%d (n/n_Lcg), BS Index %d, BS value < %d, total %d\n", - frameP, - slot, - n, - n_Lcg, - pduP[mac_subheader_len + 1 + n], - NR_LONG_BSR_TABLE[pduP[mac_subheader_len + 1 + n]], - sched_ctrl->estimated_ul_buffer); - } - - break; - - case UL_SCH_LCID_C_RNTI: - - for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { - NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i]; - if (ra->state >= WAIT_Msg3 && ra->rnti == UE->rnti) { - ra->crnti = ((pduP[1]&0xFF)<<8)|(pduP[2]&0xFF); - ra->msg3_dcch_dtch = true; - LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x\n", ra->crnti); - break; - } - } - - //38.321 section 6.1.3.2 - //fixed length - mac_len = 2; - /* Extract CRNTI value */ - break; - - case UL_SCH_LCID_SINGLE_ENTRY_PHR: - //38.321 section 6.1.3.8 - //fixed length - mac_len = 2; - /* Extract SINGLE ENTRY PHR elements for PHR calculation */ - ce_ptr = &pduP[mac_subheader_len]; - NR_SINGLE_ENTRY_PHR_MAC_CE *phr = (NR_SINGLE_ENTRY_PHR_MAC_CE *) ce_ptr; - /* Save the phr info */ - const int PH = phr->PH; - const int PCMAX = phr->PCMAX; - /* 38.133 Table10.1.17.1-1 */ - if (PH < 55) - sched_ctrl->ph = PH - 32; - else - sched_ctrl->ph = PH - 32 + (PH - 54); - /* 38.133 Table10.1.18.1-1 */ - sched_ctrl->pcmax = PCMAX - 29; - LOG_D(NR_MAC, "SINGLE ENTRY PHR R1 %d PH %d (%d dB) R2 %d PCMAX %d (%d dBm)\n", - phr->R1, PH, sched_ctrl->ph, phr->R2, PCMAX, sched_ctrl->pcmax); - break; - - case UL_SCH_LCID_MULTI_ENTRY_PHR_1_OCT: - //38.321 section 6.1.3.9 - // varialbe length - if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) - return 0; - /* Extract MULTI ENTRY PHR elements from single octet bitmap for PHR calculation */ - break; - - case UL_SCH_LCID_MULTI_ENTRY_PHR_4_OCT: - //38.321 section 6.1.3.9 - // varialbe length - if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) - return 0; - /* Extract MULTI ENTRY PHR elements from four octets bitmap for PHR calculation */ - break; - - case UL_SCH_LCID_PADDING: - done = 1; - // end of MAC PDU, can ignore the rest. - break; - - case UL_SCH_LCID_SRB1: - case UL_SCH_LCID_SRB2: - if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) - return 0; - - rnti_t crnti = UE->rnti; - NR_UE_info_t* UE_idx = UE; - for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { - NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i]; - if (ra->state >= WAIT_Msg3 && ra->rnti == UE->rnti) { - uint8_t *next_subpduP = pduP + mac_subheader_len + mac_len; - if ((pduP[mac_subheader_len+mac_len] & 0x3F) == UL_SCH_LCID_C_RNTI) { - crnti = ((next_subpduP[1]&0xFF)<<8)|(next_subpduP[2]&0xFF); - LOG_W(NR_MAC, " UL_SCH_LCID_SRB for rnti %04x\n", crnti); - UE_idx = find_nr_UE(&RC.nrmac[module_idP]->UE_info, crnti); - break; - } - } - } - - if (UE_idx->CellGroup) { - LOG_D(NR_MAC, "Frame %d : ULSCH -> UL-DCCH %d (gNB %ld, %d bytes), rnti: 0x%04x \n", frameP, rx_lcid, module_idP, mac_len, crnti); - mac_rlc_data_ind(module_idP, - crnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - rx_lcid, - (char *) (pduP + mac_subheader_len), - mac_len, - 1, - NULL); - } else { - AssertFatal(1==0,"[UE %04x] Frame/Slot %d.%d : Received LCID %d which is not configured, dropping packet\n",UE->rnti,frameP,slot,rx_lcid); - } - break; - case UL_SCH_LCID_SRB3: - // todo - break; - - case UL_SCH_LCID_CCCH: - case UL_SCH_LCID_CCCH1: - // fixed length - mac_subheader_len = 1; - - if ( rx_lcid == UL_SCH_LCID_CCCH1 ) { - // RRCResumeRequest1 message includes the full I-RNTI and has a size of 8 bytes - mac_len = 8; - - // Check if it is a valid CCCH1 message, we get all 00's messages very often - int i = 0; - for(i=0; i<(mac_subheader_len+mac_len); i++) { - if(pduP[i] != 0) { - break; - } - } - if (i == (mac_subheader_len+mac_len)) { - LOG_D(NR_MAC, "%s() Invalid CCCH1 message!, pdu_len: %d\n", __func__, pdu_len); - done = 1; - break; - } - } else { - // fixed length of 6 bytes - mac_len = 6; - } - - send_initial_ul_rrc_message(module_idP, - CC_id, - UE, - CCCH, - pduP + mac_subheader_len, - mac_len); - break; - - case UL_SCH_LCID_DTCH ... (UL_SCH_LCID_DTCH + 28): - // check if LCID is valid at current time. - if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) { - return 0; - } - - - LOG_D(NR_MAC, "[UE %04x] %d.%d : ULSCH -> UL-%s %d (gNB %ld, %d bytes)\n", - UE->rnti, - frameP, - slot, - rx_lcid<4?"DCCH":"DTCH", - rx_lcid, - module_idP, - mac_len); - UE->mac_stats.ul.lc_bytes[rx_lcid] += mac_len; - - mac_rlc_data_ind(module_idP, - UE->rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - rx_lcid, - (char *)(pduP + mac_subheader_len), - mac_len, - 1, - NULL); - - sdus += 1; - /* Updated estimated buffer when receiving data */ - if (sched_ctrl->estimated_ul_buffer >= mac_len) { - sched_ctrl->estimated_ul_buffer -= mac_len; - } else { - sched_ctrl->estimated_ul_buffer = 0; - } - - break; - sdus += 1; - - default: - LOG_E(NR_MAC, "Received unknown MAC header (LCID = 0x%02x)\n", rx_lcid); - return -1; - break; - } - - #ifdef ENABLE_MAC_PAYLOAD_DEBUG - if (rx_lcid < 45 || rx_lcid == 52 || rx_lcid == 63) { - LOG_I(NR_MAC, "In %s: dumping UL MAC SDU sub-header with length %d (LCID = 0x%02x):\n", __func__, mac_subheader_len, rx_lcid); - log_dump(NR_MAC, pduP, mac_subheader_len, LOG_DUMP_CHAR, "\n"); - LOG_I(NR_MAC, "In %s: dumping UL MAC SDU with length %d (LCID = 0x%02x):\n", __func__, mac_len, rx_lcid); - log_dump(NR_MAC, pduP + mac_subheader_len, mac_len, LOG_DUMP_CHAR, "\n"); - } else { - LOG_I(NR_MAC, "In %s: dumping UL MAC CE with length %d (LCID = 0x%02x):\n", __func__, mac_len, rx_lcid); - log_dump(NR_MAC, pduP + mac_subheader_len + mac_len, mac_len, LOG_DUMP_CHAR, "\n"); - } - #endif - - pduP += ( mac_subheader_len + mac_len ); - pdu_len -= ( mac_subheader_len + mac_len ); - - if (pdu_len < 0) { - LOG_E(NR_MAC, "In %s: residual UL MAC PDU in %d.%d with length < 0!, pdu_len %d \n", __func__, frameP, slot, pdu_len); - LOG_E(NR_MAC, "MAC PDU "); - for (int i = 0; i < 20; i++) // Only printf 1st - 20nd bytes - printf("%02x ", pduP[i]); - printf("\n"); + switch(rx_lcid){ + // MAC CE + /*#ifdef DEBUG_HEADER_PARSING + LOG_D(NR_MAC, "[UE] LCID %d, PDU length %d\n", ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID, pdu_len); + #endif*/ + case UL_SCH_LCID_RECOMMENDED_BITRATE_QUERY: + // 38.321 Ch6.1.3.20 + mac_len = 2; + break; + case UL_SCH_LCID_CONFIGURED_GRANT_CONFIRMATION: + // 38.321 Ch6.1.3.7 + break; + case UL_SCH_LCID_S_BSR: + case UL_SCH_LCID_S_TRUNCATED_BSR: + //38.321 section 6.1.3.1 + //fixed length + mac_len =1; + /* Extract short BSR value */ + ce_ptr = &pduP[mac_subheader_len]; + NR_BSR_SHORT *bsr_s = (NR_BSR_SHORT *) ce_ptr; + sched_ctrl->estimated_ul_buffer = 0; + sched_ctrl->estimated_ul_buffer = NR_SHORT_BSR_TABLE[bsr_s->Buffer_size]; + LOG_D(NR_MAC, + "SHORT BSR at %4d.%2d, LCG ID %d, BS Index %d, BS value < %d, est buf %d\n", + frameP, + slot, + bsr_s->LcgID, + bsr_s->Buffer_size, + NR_SHORT_BSR_TABLE[bsr_s->Buffer_size], + sched_ctrl->estimated_ul_buffer); + break; + case UL_SCH_LCID_L_BSR: + case UL_SCH_LCID_L_TRUNCATED_BSR: + //38.321 section 6.1.3.1 + //variable length + /* Several checks have been added to this function to + ensure that the casting of the pduP is possible. There seems + to be a partial PDU at the end of this buffer, so here + we gracefully ignore that by returning 0. See: + https://gitlab.eurecom.fr/oai/openairinterface5g/-/issues/534 */ + if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) return 0; + /* Extract long BSR value */ + ce_ptr = &pduP[mac_subheader_len]; + NR_BSR_LONG *bsr_l = (NR_BSR_LONG *) ce_ptr; + sched_ctrl->estimated_ul_buffer = 0; + + n_Lcg = bsr_l->LcgID7 + bsr_l->LcgID6 + bsr_l->LcgID5 + bsr_l->LcgID4 + + bsr_l->LcgID3 + bsr_l->LcgID2 + bsr_l->LcgID1 + bsr_l->LcgID0; + + LOG_D(NR_MAC, "LONG BSR, LCG ID(7-0) %d/%d/%d/%d/%d/%d/%d/%d\n", + bsr_l->LcgID7, bsr_l->LcgID6, bsr_l->LcgID5, bsr_l->LcgID4, + bsr_l->LcgID3, bsr_l->LcgID2, bsr_l->LcgID1, bsr_l->LcgID0); + + for (int n = 0; n < n_Lcg; n++){ + LOG_D(NR_MAC, "LONG BSR, %d/%d (n/n_Lcg), BS Index %d, BS value < %d", + n, n_Lcg, pduP[mac_subheader_len + 1 + n], + NR_LONG_BSR_TABLE[pduP[mac_subheader_len + 1 + n]]); + sched_ctrl->estimated_ul_buffer += NR_LONG_BSR_TABLE[pduP[mac_subheader_len + 1 + n]]; + LOG_D(NR_MAC, + "LONG BSR at %4d.%2d, %d/%d (n/n_Lcg), BS Index %d, BS value < %d, total %d\n", + frameP, + slot, + n, + n_Lcg, + pduP[mac_subheader_len + 1 + n], + NR_LONG_BSR_TABLE[pduP[mac_subheader_len + 1 + n]], + sched_ctrl->estimated_ul_buffer); } - } + + break; + + case UL_SCH_LCID_C_RNTI: + + for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { + NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i]; + if (ra->state >= WAIT_Msg3 && ra->rnti == UE->rnti) { + ra->crnti = ((pduP[1]&0xFF)<<8)|(pduP[2]&0xFF); + ra->msg3_dcch_dtch = true; + LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x\n", ra->crnti); + break; + } + } + + //38.321 section 6.1.3.2 + //fixed length + mac_len = 2; + /* Extract CRNTI value */ + break; + + case UL_SCH_LCID_SINGLE_ENTRY_PHR: + AssertFatal(harq_pid>-1,"Invalid HARQ PID %d\n",harq_pid); + NR_sched_pusch_t *sched_pusch = &sched_ctrl->ul_harq_processes[harq_pid].sched_pusch;; + //38.321 section 6.1.3.8 + //fixed length + mac_len = 2; + /* Extract SINGLE ENTRY PHR elements for PHR calculation */ + ce_ptr = &pduP[mac_subheader_len]; + NR_SINGLE_ENTRY_PHR_MAC_CE *phr = (NR_SINGLE_ENTRY_PHR_MAC_CE *) ce_ptr; + /* Save the phr info */ + int PH; + const int PCMAX = phr->PCMAX; + /* 38.133 Table10.1.17.1-1 */ + if (phr->PH < 55) + PH = phr->PH - 32; + else + PH = phr->PH - 32 + (phr->PH - 54); + // in sched_ctrl we set normalized PH wrt MCS and PRBs + long *deltaMCS = ul_bwp->pusch_Config ? ul_bwp->pusch_Config->pusch_PowerControl->deltaMCS : NULL; + sched_ctrl->ph = PH + + compute_bw_factor(sched_pusch->mu, sched_pusch->rbSize) + + compute_delta_tf(sched_pusch->tb_size<<3, + sched_pusch->rbSize, + 0, //n_layers + 0, //n_symbols + 0, //n_dmrs + deltaMCS); + /* 38.133 Table10.1.18.1-1 */ + sched_ctrl->pcmax = PCMAX - 29; + LOG_D(NR_MAC, "SINGLE ENTRY PHR R1 %d PH %d (%d dB) R2 %d PCMAX %d (%d dBm)\n", + phr->R1, PH, sched_ctrl->ph, phr->R2, PCMAX, sched_ctrl->pcmax); + break; + + case UL_SCH_LCID_MULTI_ENTRY_PHR_1_OCT: + //38.321 section 6.1.3.9 + // varialbe length + if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) + return 0; + /* Extract MULTI ENTRY PHR elements from single octet bitmap for PHR calculation */ + break; + + case UL_SCH_LCID_MULTI_ENTRY_PHR_4_OCT: + //38.321 section 6.1.3.9 + // varialbe length + if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) + return 0; + /* Extract MULTI ENTRY PHR elements from four octets bitmap for PHR calculation */ + break; + + case UL_SCH_LCID_PADDING: + done = 1; + // end of MAC PDU, can ignore the rest. + break; + + case UL_SCH_LCID_SRB1: + case UL_SCH_LCID_SRB2: + if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) + return 0; + + rnti_t crnti = UE->rnti; + NR_UE_info_t* UE_idx = UE; + for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { + NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i]; + if (ra->state >= WAIT_Msg3 && ra->rnti == UE->rnti) { + uint8_t *next_subpduP = pduP + mac_subheader_len + mac_len; + if ((pduP[mac_subheader_len+mac_len] & 0x3F) == UL_SCH_LCID_C_RNTI) { + crnti = ((next_subpduP[1]&0xFF)<<8)|(next_subpduP[2]&0xFF); + LOG_W(NR_MAC, " UL_SCH_LCID_SRB for rnti %04x\n", crnti); + UE_idx = find_nr_UE(&RC.nrmac[module_idP]->UE_info, crnti); + break; + } + } + } + + if (UE_idx->CellGroup) { + LOG_D(NR_MAC, "Frame %d : ULSCH -> UL-DCCH %d (gNB %ld, %d bytes), rnti: 0x%04x \n", frameP, rx_lcid, module_idP, mac_len, crnti); + mac_rlc_data_ind(module_idP, + crnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + rx_lcid, + (char *) (pduP + mac_subheader_len), + mac_len, + 1, + NULL); + } else { + AssertFatal(1==0,"[UE %04x] Frame/Slot %d.%d : Received LCID %d which is not configured, dropping packet\n",UE->rnti,frameP,slot,rx_lcid); + } + break; + + case UL_SCH_LCID_CCCH: + case UL_SCH_LCID_CCCH1: + // fixed length + mac_subheader_len = 1; + + if ( rx_lcid == UL_SCH_LCID_CCCH1 ) { + // RRCResumeRequest1 message includes the full I-RNTI and has a size of 8 bytes + mac_len = 8; + + // Check if it is a valid CCCH1 message, we get all 00's messages very often + int i = 0; + for(i=0; i<(mac_subheader_len+mac_len); i++) { + if(pduP[i] != 0) { + break; + } + } + if (i == (mac_subheader_len+mac_len)) { + LOG_D(NR_MAC, "%s() Invalid CCCH1 message!, pdu_len: %d\n", __func__, pdu_len); + done = 1; + break; + } + } else { + // fixed length of 6 bytes + mac_len = 6; + } + + send_initial_ul_rrc_message(module_idP, + CC_id, + UE, + CCCH, + pduP + mac_subheader_len, + mac_len); + break; + + case UL_SCH_LCID_DTCH ... (UL_SCH_LCID_DTCH + 28): + // check if LCID is valid at current time. + if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) + return 0; + + LOG_D(NR_MAC, "[UE %04x] %d.%d : ULSCH -> UL-%s %d (gNB %ld, %d bytes)\n", + UE->rnti, + frameP, + slot, + rx_lcid<4?"DCCH":"DTCH", + rx_lcid, + module_idP, + mac_len); + UE->mac_stats.ul.lc_bytes[rx_lcid] += mac_len; + + mac_rlc_data_ind(module_idP, + UE->rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + rx_lcid, + (char *)(pduP + mac_subheader_len), + mac_len, + 1, + NULL); + + sdus += 1; + /* Updated estimated buffer when receiving data */ + if (sched_ctrl->estimated_ul_buffer >= mac_len) + sched_ctrl->estimated_ul_buffer -= mac_len; + else + sched_ctrl->estimated_ul_buffer = 0; + break; + + default: + LOG_E(NR_MAC, "Received unknown MAC header (LCID = 0x%02x)\n", rx_lcid); + return -1; + break; + } + +#ifdef ENABLE_MAC_PAYLOAD_DEBUG + if (rx_lcid < 45 || rx_lcid == 52 || rx_lcid == 63) { + LOG_I(NR_MAC, "In %s: dumping UL MAC SDU sub-header with length %d (LCID = 0x%02x):\n", __func__, mac_subheader_len, rx_lcid); + log_dump(NR_MAC, pduP, mac_subheader_len, LOG_DUMP_CHAR, "\n"); + LOG_I(NR_MAC, "In %s: dumping UL MAC SDU with length %d (LCID = 0x%02x):\n", __func__, mac_len, rx_lcid); + log_dump(NR_MAC, pduP + mac_subheader_len, mac_len, LOG_DUMP_CHAR, "\n"); + } else { + LOG_I(NR_MAC, "In %s: dumping UL MAC CE with length %d (LCID = 0x%02x):\n", __func__, mac_len, rx_lcid); + log_dump(NR_MAC, pduP + mac_subheader_len + mac_len, mac_len, LOG_DUMP_CHAR, "\n"); + } +#endif + + pduP += ( mac_subheader_len + mac_len ); + pdu_len -= ( mac_subheader_len + mac_len ); + + if (pdu_len < 0) { + LOG_E(NR_MAC, "In %s: residual UL MAC PDU in %d.%d with length < 0!, pdu_len %d \n", __func__, frameP, slot, pdu_len); + LOG_E(NR_MAC, "MAC PDU "); + for (int i = 0; i < 20; i++) // Only printf 1st - 20nd bytes + printf("%02x ", pduP[i]); + printf("\n"); + return 0; + } + } UE->mac_stats.ul.num_mac_sdu += sdus; @@ -547,9 +574,9 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, LOG_I(NR_MAC, "Printing received UL MAC payload at gNB side: %d \n"); for (int i = 0; i < sdu_lenP ; i++) { - //harq_process_ul_ue->a[i] = (unsigned char) rand(); - //printf("a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); - printf("%02x ",(unsigned char)sduP[i]); + //harq_process_ul_ue->a[i] = (unsigned char) rand(); + //printf("a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); + printf("%02x ",(unsigned char)sduP[i]); } printf("\n"); @@ -564,7 +591,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, if (UE_scheduling_control->sched_ul_bytes < 0) UE_scheduling_control->sched_ul_bytes = 0; - nr_process_mac_pdu(gnb_mod_idP, UE, CC_idP, frameP, slotP, sduP, sdu_lenP); + nr_process_mac_pdu(gnb_mod_idP, UE, CC_idP, frameP, slotP, sduP, sdu_lenP, harq_pid); } else { NR_UE_ul_harq_t *cur_harq = &UE_scheduling_control->ul_harq_processes[harq_pid]; @@ -663,14 +690,14 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, current_rnti, ra->rnti); - NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl; + NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl; - UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10,ul_cqi,30); - if (timing_advance != 0xffff) - UE_scheduling_control->ta_update = timing_advance; - UE_scheduling_control->raw_rssi = rssi; - UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640; - LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n",UE->rnti,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update); + UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10,ul_cqi,30); + if (timing_advance != 0xffff) + UE_scheduling_control->ta_update = timing_advance; + UE_scheduling_control->raw_rssi = rssi; + UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640; + LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n",UE->rnti,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update); if(ra->cfra) { LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", ra->rnti); @@ -691,8 +718,9 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, // Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to fill in Msg4 // First byte corresponds to R/LCID MAC sub-header memcpy(ra->cont_res_id, &sduP[1], sizeof(uint8_t) * 6); - - if (nr_process_mac_pdu(gnb_mod_idP, UE, CC_idP, frameP, slotP, sduP, sdu_lenP) == 0) { + // harq_pid set a non valid value because it is not used in this call + // the function is only called to decode the contention resolution sub-header + if (nr_process_mac_pdu(gnb_mod_idP, UE, CC_idP, frameP, slotP, sduP, sdu_lenP, -1) == 0) { ra->state = Msg4; ra->Msg4_frame = (frameP + 2) % 1024; ra->Msg4_slot = 1; @@ -864,6 +892,65 @@ static bool nr_UE_is_to_be_scheduled(const NR_ServingCellConfigCommon_t *scc, return has_data || sched_ctrl->SR || high_inactivity; } +void update_ul_ue_R_Qm(int mcs, int mcs_table, const NR_PUSCH_Config_t *pusch_Config, uint16_t *R, uint8_t *Qm) +{ + *R = nr_get_code_rate_ul(mcs, mcs_table); + *Qm = nr_get_Qm_ul(mcs, mcs_table); + + if (pusch_Config && pusch_Config->tp_pi2BPSK && ((mcs_table == 3 && mcs < 2) || (mcs_table == 4 && mcs < 6))) { + *R >>= 1; + *Qm <<= 1; + } +} + + +void nr_ue_max_mcs_min_rb(int mu, int ph_limit, NR_pusch_semi_static_t *ps, NR_UE_UL_BWP_t *ul_bwp, uint16_t minRb, uint32_t tbs, uint16_t *Rb, uint8_t *mcs) +{ + AssertFatal(*Rb >= minRb, "illegal Rb %d < minRb %d\n", *Rb, minRb); + AssertFatal(*mcs >= 0 && *mcs <= 28, "illegal MCS %d\n", *mcs); + + const int tbs_bits = tbs << 3; + uint16_t R; + uint8_t Qm; + update_ul_ue_R_Qm(*mcs, ul_bwp->mcs_table, ul_bwp->pusch_Config, &R, &Qm); + + long *deltaMCS = ul_bwp->pusch_Config ? ul_bwp->pusch_Config->pusch_PowerControl->deltaMCS : NULL; + int tx_power = compute_bw_factor(mu, *Rb) + + compute_delta_tf(tbs_bits, + *Rb, + ps->nrOfLayers, + ps->nrOfSymbols, + ps->N_PRB_DMRS*ps->num_dmrs_symb, + deltaMCS); + + while (ph_limit < tx_power && *Rb >= minRb) { + (*Rb)--; + tx_power = compute_bw_factor(mu, *Rb) + + compute_delta_tf(tbs_bits, + *Rb, + ps->nrOfLayers, + ps->nrOfSymbols, + ps->N_PRB_DMRS*ps->num_dmrs_symb, + deltaMCS); + } + + while (ph_limit < tx_power && *mcs > 6) { + (*mcs)--; + update_ul_ue_R_Qm(*mcs, ul_bwp->mcs_table, ul_bwp->pusch_Config, &R, &Qm); + tx_power = compute_bw_factor(mu, *Rb) + + compute_delta_tf(tbs_bits, + *Rb, + ps->nrOfLayers, + ps->nrOfSymbols, + ps->N_PRB_DMRS*ps->num_dmrs_symb, + deltaMCS); + } + + if (ph_limit < tx_power) + LOG_W(NR_MAC, "Normalized power %d based on current resources (RBs %d, MCS %d) exceed reported PHR %d (normalized value)\n", + tx_power, *Rb, *mcs, ph_limit); +} + static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, frame_t frame, sub_frame_t slot, @@ -1006,18 +1093,6 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, return true; } -void update_ul_ue_R_Qm(NR_sched_pusch_t *sched_pusch, const NR_PUSCH_Config_t *pusch_Config, const int mcs_table) { - - const int mcs = sched_pusch->mcs; - sched_pusch->R = nr_get_code_rate_ul(mcs, mcs_table); - sched_pusch->Qm = nr_get_Qm_ul(mcs, mcs_table); - - if (pusch_Config && pusch_Config->tp_pi2BPSK && ((mcs_table == 3 && mcs < 2) || (mcs_table == 4 && mcs < 6))) { - sched_pusch->R >>= 1; - sched_pusch->Qm <<= 1; - } -} - uint32_t ul_pf_tbs[3][29]; // pre-computed, approximate TBS values for PF coefficient typedef struct UEsched_s { float coef; @@ -1188,7 +1263,7 @@ void pf_ul(module_id_t module_id, NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; sched_pusch->mcs = min(nrmac->min_grant_mcs, sched_pusch->mcs); - update_ul_ue_R_Qm(sched_pusch, current_BWP->pusch_Config, current_BWP->mcs_table); + update_ul_ue_R_Qm(sched_pusch->mcs, current_BWP->mcs_table, current_BWP->pusch_Config, &sched_pusch->R, &sched_pusch->Qm); sched_pusch->rbStart = rbStart; sched_pusch->rbSize = min_rb; sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm, @@ -1274,7 +1349,7 @@ void pf_ul(module_id_t module_id, nrOfLayers, ps); } - update_ul_ue_R_Qm(sched_pusch, current_BWP->pusch_Config, current_BWP->mcs_table); + update_ul_ue_R_Qm(sched_pusch->mcs, current_BWP->mcs_table, current_BWP->pusch_Config, &sched_pusch->R, &sched_pusch->Qm); int rbStart = 0; const uint16_t slbitmap = SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols); @@ -1293,8 +1368,17 @@ void pf_ul(module_id_t module_id, else LOG_D(NR_MAC,"allocating UL data for RNTI %04x (rbStsart %d, min_rb %d, bwpSize %d)\n", iterator->UE->rnti,rbStart,min_rb,bwpSize); - /* Calculate the current scheduling bytes and the necessary RBs */ + /* Calculate the current scheduling bytes */ const int B = cmax(sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes, 0); + /* adjust rbSize and MCS according to PHR and BPRE */ + sched_pusch->mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; + if(sched_ctrl->pcmax!=0 || + sched_ctrl->ph!=0) // verify if the PHR related parameter have been initialized + nr_ue_max_mcs_min_rb(sched_pusch->mu, sched_ctrl->ph, ps, current_BWP, min_rbSize, B, &max_rbSize, &sched_pusch->mcs); + + if (sched_pusch->mcs < sched_ctrl->ul_bler_stats.mcs) + sched_ctrl->ul_bler_stats.mcs = sched_pusch->mcs; /* force estimated MCS down */ + uint16_t rbSize = 0; uint32_t TBS = 0; @@ -1308,6 +1392,7 @@ void pf_ul(module_id_t module_id, max_rbSize, &TBS, &rbSize); + sched_pusch->rbSize = rbSize; sched_pusch->tb_size = TBS; LOG_D(NR_MAC,"rbSize %d (max_rbSize %d), TBS %d, est buf %d, sched_ul %d, B %d, CCE %d, num_dmrs_symb %d, N_PRB_DMRS %d\n", @@ -1692,6 +1777,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) pusch_pdu->pusch_data.tb_size = sched_pusch->tb_size; pusch_pdu->pusch_data.num_cb = 0; //CBG not supported + pusch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(sched_pusch->tb_size<<3,sched_pusch->R); if(current_BWP->pusch_servingcellconfig && current_BWP->pusch_servingcellconfig->rateMatching) { // TBS_LBRM according to section 5.4.2.1 of 38.212 diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 674d80a4d4..6a3f778af9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -469,7 +469,6 @@ uint16_t set_pm_index(NR_UE_sched_ctrl_t *sched_ctrl, int codebook_mode); uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx); - uint8_t set_dl_nrOfLayers(NR_UE_sched_ctrl_t *sched_ctrl); const int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 241cb663b4..346f1f8516 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -394,6 +394,7 @@ typedef struct NR_pusch_semi_static_t { typedef struct NR_sched_pusch { int frame; int slot; + int mu; /// RB allocation within active uBWP uint16_t rbSize; diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 04b0bb2d3c..47b6e38402 100755 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -1664,12 +1664,7 @@ void fill_initial_cellGroupConfig(int uid, tag->tag_Id = 0; tag->timeAlignmentTimer = NR_TimeAlignmentTimer_infinity; ASN_SEQUENCE_ADD(&mac_CellGroupConfig->tag_Config->tag_ToAddModList->list,tag); - mac_CellGroupConfig->phr_Config = calloc(1, sizeof(*mac_CellGroupConfig->phr_Config)); - mac_CellGroupConfig->phr_Config->present = NR_SetupRelease_PHR_Config_PR_setup; - mac_CellGroupConfig->phr_Config->choice.setup = calloc(1, sizeof(*mac_CellGroupConfig->phr_Config->choice.setup)); - mac_CellGroupConfig->phr_Config->choice.setup->phr_PeriodicTimer = NR_PHR_Config__phr_PeriodicTimer_sf10; - mac_CellGroupConfig->phr_Config->choice.setup->phr_ProhibitTimer = NR_PHR_Config__phr_ProhibitTimer_sf10; - mac_CellGroupConfig->phr_Config->choice.setup->phr_Tx_PowerFactorChange = NR_PHR_Config__phr_Tx_PowerFactorChange_dB1; + set_phr_config(mac_CellGroupConfig); mac_CellGroupConfig->schedulingRequestConfig = calloc(1, sizeof(*mac_CellGroupConfig->schedulingRequestConfig)); mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToAddModList = CALLOC(1,sizeof(*mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToAddModList)); diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 9a1d137a8c..deb2c4965e 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -1147,4 +1147,13 @@ void config_uplinkBWP(NR_BWP_Uplink_t *ubwp, ubwp->bwp_Dedicated->beamFailureRecoveryConfig = NULL; } +void set_phr_config(NR_MAC_CellGroupConfig_t *mac_CellGroupConfig) +{ + mac_CellGroupConfig->phr_Config = calloc(1, sizeof(*mac_CellGroupConfig->phr_Config)); + mac_CellGroupConfig->phr_Config->present = NR_SetupRelease_PHR_Config_PR_setup; + mac_CellGroupConfig->phr_Config->choice.setup = calloc(1, sizeof(*mac_CellGroupConfig->phr_Config->choice.setup)); + mac_CellGroupConfig->phr_Config->choice.setup->phr_PeriodicTimer = NR_PHR_Config__phr_PeriodicTimer_sf10; + mac_CellGroupConfig->phr_Config->choice.setup->phr_ProhibitTimer = NR_PHR_Config__phr_ProhibitTimer_sf10; + mac_CellGroupConfig->phr_Config->choice.setup->phr_Tx_PowerFactorChange = NR_PHR_Config__phr_Tx_PowerFactorChange_dB1; +} diff --git a/openair2/RRC/NR/nr_rrc_config.h b/openair2/RRC/NR/nr_rrc_config.h index 49922aed6b..f8bdc4be53 100644 --- a/openair2/RRC/NR/nr_rrc_config.h +++ b/openair2/RRC/NR/nr_rrc_config.h @@ -119,6 +119,7 @@ typedef struct physicalcellgroup_s{ long RNTI_Value[MAX_NUM_CCs]; }physicalcellgroup_t; +void set_phr_config(NR_MAC_CellGroupConfig_t *mac_CellGroupConfig); uint64_t get_ssb_bitmap(const NR_ServingCellConfigCommon_t *scc); void rrc_coreset_config(NR_ControlResourceSet_t *coreset, int bwp_id, diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index 0f1da63510..1dca25b618 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -133,16 +133,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco tag->tag_Id = 0; tag->timeAlignmentTimer = NR_TimeAlignmentTimer_infinity; ASN_SEQUENCE_ADD(&mac_CellGroupConfig->tag_Config->tag_ToAddModList->list,tag); - mac_CellGroupConfig->phr_Config = calloc(1,sizeof(*mac_CellGroupConfig->phr_Config)); - mac_CellGroupConfig->phr_Config->present = NR_SetupRelease_PHR_Config_PR_setup; - mac_CellGroupConfig->phr_Config->choice.setup = calloc(1,sizeof(*mac_CellGroupConfig->phr_Config->choice.setup)); - mac_CellGroupConfig->phr_Config->choice.setup->phr_PeriodicTimer = NR_PHR_Config__phr_PeriodicTimer_sf20; - mac_CellGroupConfig->phr_Config->choice.setup->phr_ProhibitTimer = NR_PHR_Config__phr_ProhibitTimer_sf0; - mac_CellGroupConfig->phr_Config->choice.setup->phr_Tx_PowerFactorChange = NR_PHR_Config__phr_Tx_PowerFactorChange_dB3; - mac_CellGroupConfig->phr_Config->choice.setup->multiplePHR=false; - mac_CellGroupConfig->phr_Config->choice.setup->dummy=false; - mac_CellGroupConfig->phr_Config->choice.setup->phr_Type2OtherCell = false; - mac_CellGroupConfig->phr_Config->choice.setup->phr_ModeOtherCG = NR_PHR_Config__phr_ModeOtherCG_real; + set_phr_config(mac_CellGroupConfig); mac_CellGroupConfig->skipUplinkTxDynamic=false; mac_CellGroupConfig->ext1 = NULL; secondaryCellGroup->physicalCellGroupConfig = calloc(1,sizeof(*secondaryCellGroup->physicalCellGroupConfig));