From 22a4480c2ae3cc0e1258d1574dc0c573dd77a83f Mon Sep 17 00:00:00 2001 From: ndomingues Date: Tue, 14 May 2024 11:24:04 +0100 Subject: [PATCH 01/15] Add configuration file with support for RA 2-Step --- openair2/GNB_APP/RRC_nr_paramsvalues.h | 37 +++ ...b.sa.band78.106PRB.usrpb210.RA_2-Step.conf | 278 ++++++++++++++++++ 2 files changed, 315 insertions(+) create mode 100644 targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.106PRB.usrpb210.RA_2-Step.conf diff --git a/openair2/GNB_APP/RRC_nr_paramsvalues.h b/openair2/GNB_APP/RRC_nr_paramsvalues.h index bfda253fbf..34daf12090 100644 --- a/openair2/GNB_APP/RRC_nr_paramsvalues.h +++ b/openair2/GNB_APP/RRC_nr_paramsvalues.h @@ -91,6 +91,22 @@ #define GNB_CONFIG_STRING_P0NOMINAL "p0_nominal" #define GNB_CONFIG_STRING_PUCCHRES "pucch_ResourceCommon" +#define GNB_CONFIG_STRING_MSGBRESPONSEWINDOW_R16 "msgB_ResponseWindow_r16" +#define GNB_CONFIG_STRING_MSGARSRPTHRESHOLD_R16 "msgA_RSRP_Threshold_r16" +#define GNB_CONFIG_STRING_MSGACBPREAMBLESPERSHAREDRO_R16 "msgA_CB_PreamblesPerSSB_PerSharedRO_r16" +#define GNB_CONFIG_STRING_MSGAMCS_R16 "msgA_MCS_r16" +#define GNB_CONFIG_STRING_NROFSLOTSMSGAPUSCH_R16 "nrofSlotsMsgA_PUSCH_r16" +#define GNB_CONFIG_STRING_NROFMSGAPOPERSLOT_R16 "nrofMsgA_PO_PerSlot_r16" +#define GNB_CONFIG_STRING_MSGAPUSCHTIMEDOMAINOFFSET_R16 "msgA_PUSCH_TimeDomainOffset_r16" +#define GNB_CONFIG_STRING_STARTSYMBOLANDLENGTHMSGA_PO_R16 "startSymbolAndLengthMsgA_PO_r16" +#define GNB_CONFIG_STRING_MAPPINGTYPEMSGAPUSCH_R16 "mappingTypeMsgA_PUSCH_r16" +#define GNB_CONFIG_STRING_GUARDBANDMSGAPUSCH_R16 "guardBandMsgA_PUSCH_r16" +#define GNB_CONFIG_STRING_FREQUENCYSTARTMSGAPUSCH_R16 "frequencyStartMsgA_PUSCH_r16" +#define GNB_CONFIG_STRING_NROFPRBSPERMSGAPO_R16 "nrofPRBs_PerMsgA_PO_r16" +#define GNB_CONFIG_STRING_NROFMSGAPOFDM_R16 "nrofMsgA_PO_FDM_r16" +#define GNB_CONFIG_STRING_MSGAPUSCHNROFPORTS_R16 "msgA_PUSCH_NrofPorts_r16" +#define GNB_CONFIG_STRING_NROFDMRSSEQUENCES_R16 "nrofDMRS_Sequences_r16" +#define GNB_CONFIG_STRING_MSGATRANSFORMPRECODER_R16 "msgA_TransformPrecoder_r16" #define GNB_CONFIG_STRING_SSBPOSITIONSINBURST "ssb_PositionsInBurst_Bitmap" #define GNB_CONFIG_STRING_SSBPERIODICITYSERVINGCELL "ssb_periodicityServingCell" @@ -296,4 +312,25 @@ {GNB_CONFIG_STRING_LOCATIONANDBANDWIDTH_ULBWP4,NULL,0,.i64ptr=&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[3]->bwp_Common->genericParameters.locationAndBandwidth,.defint64val=0,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_DEFAULTDLBWP_ID,NULL,0,.i64ptr=scd->defaultDownlinkBWP_Id,.defint64val=0,TYPE_INT64,0}} +/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* Serving Cell Config Common configuration parameters to apply in RA 2-Step */ +/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ + +#define MSGASCCPARAMS_DESC(scc) { \ +{GNB_CONFIG_STRING_MSGBRESPONSEWINDOW_R16,NULL,0,.i64ptr=scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->rach_ConfigCommonTwoStepRA_r16.rach_ConfigGenericTwoStepRA_r16.msgB_ResponseWindow_r16,.defintval=-1,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_MSGARSRPTHRESHOLD_R16,NULL,0,.i64ptr=scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->rach_ConfigCommonTwoStepRA_r16.msgA_RSRP_Threshold_r16,.defintval=19,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_MSGAMCS_R16,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16->msgA_MCS_r16,.defintval=2,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_NROFSLOTSMSGAPUSCH_R16,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16->nrofSlotsMsgA_PUSCH_r16,.defintval=1,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_NROFMSGAPOPERSLOT_R16,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16->nrofMsgA_PO_PerSlot_r16,.defintval=NR_MsgA_PUSCH_Resource_r16__nrofMsgA_PO_PerSlot_r16_one,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_MSGAPUSCHTIMEDOMAINOFFSET_R16,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16->msgA_PUSCH_TimeDomainOffset_r16,.defintval=0,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_STARTSYMBOLANDLENGTHMSGA_PO_R16,NULL,0,.i64ptr=scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16->startSymbolAndLengthMsgA_PO_r16,.defintval=38,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_MAPPINGTYPEMSGAPUSCH_R16,NULL,0,.i64ptr=scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16->mappingTypeMsgA_PUSCH_r16,.defintval=0,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_GUARDBANDMSGAPUSCH_R16,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16->guardBandMsgA_PUSCH_r16,.defintval=0,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_FREQUENCYSTARTMSGAPUSCH_R16,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16->frequencyStartMsgA_PUSCH_r16,.defintval=0,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_NROFPRBSPERMSGAPO_R16,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16->nrofPRBs_PerMsgA_PO_r16,.defintval=8,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_NROFMSGAPOFDM_R16,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16->nrofMsgA_PO_FDM_r16,.defintval=NR_MsgA_PUSCH_Resource_r16__nrofMsgA_PO_FDM_r16_one,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_MSGAPUSCHNROFPORTS_R16,NULL,0,.i64ptr=scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16->msgA_DMRS_Config_r16.msgA_PUSCH_NrofPorts_r16,.defintval=1,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_NROFDMRSSEQUENCES_R16,NULL,0,.i64ptr=&scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16->nrofDMRS_Sequences_r16,.defintval=1,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_MSGATRANSFORMPRECODER_R16,NULL,0,.i64ptr=scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->msgA_PUSCH_Config_r16->msgA_TransformPrecoder_r16,.defintval=NR_MsgA_PUSCH_Config_r16__msgA_TransformPrecoder_r16_disabled,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_MSGACBPREAMBLESPERSHAREDRO_R16,NULL,0,.i64ptr=scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->rach_ConfigCommonTwoStepRA_r16.msgA_CB_PreamblesPerSSB_PerSharedRO_r16,.defintval=1,TYPE_INT64,0}} #endif diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.106PRB.usrpb210.RA_2-Step.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.106PRB.usrpb210.RA_2-Step.conf new file mode 100644 index 0000000000..45dbf2197f --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.106PRB.usrpb210.RA_2-Step.conf @@ -0,0 +1,278 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1; }) }); + + nr_cellid = 12345678L; + + ////////// Physical parameters: + + do_CSIRS = 1; + do_SRS = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641280; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640008; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952 +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + + # 0=sl1, 1=sl2, 2=sl4, 3=sl8, 4=sl10, 5=sl20, 6=sl40, 7=sl80, 8=sl160, 9=sl320 + msgB_ResponseWindow_r16 = 2; + msgA_RSRP_Threshold_r16 = 19; + + msgA_CB_PreamblesPerSSB_PerSharedRO_r16 = 1; + + msgA_MCS_r16 = 2; + nrofSlotsMsgA_PUSCH_r16 = 1; + # 0=one, 1=two, 2=three, 3=six + nrofMsgA_PO_PerSlot_r16 = 0; + msgA_PUSCH_TimeDomainOffset_r16 = 8; + startSymbolAndLengthMsgA_PO_r16 = 38; + mappingTypeMsgA_PUSCH_r16 = 0; + guardBandMsgA_PUSCH_r16 = 0; + frequencyStartMsgA_PUSCH_r16 = 0; + nrofPRBs_PerMsgA_PO_r16 = 8; + # 0=one, 1=two, 2=four, 3=eight + nrofMsgA_PO_FDM_r16 = 0; + msgA_PUSCH_NrofPorts_r16 = 1; + nrofDMRS_Sequences_r16 = 1; + # 0=enabled, 1=disabled + msgA_TransformPrecoder_r16 = 1; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "192.168.70.132"; }); + + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 150; + pucch_TargetSNRx10 = 200; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 100; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( +{ + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 12; + att_rx = 12; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + #beamforming 1x4 matrix: + bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + clock_src = "internal"; +} +); + +rfsimulator : +{ + serveraddr = "server"; + serverport = 4043; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="debug"; + f1ap_log_level ="debug"; +}; + +e2_agent = { + near_ric_ip_addr = "127.0.0.1"; + #sm_dir = "/path/where/the/SMs/are/located/" + sm_dir = "/usr/local/lib/flexric/" +}; From e4655154eeea41905cad87b67cc004bfa53458aa Mon Sep 17 00:00:00 2001 From: ndomingues Date: Tue, 14 May 2024 11:24:48 +0100 Subject: [PATCH 02/15] Add RA 2-Step configuration parameters to SIB1 --- openair1/SIMULATION/NR_PHY/nr_unitary_defs.h | 1 + openair2/GNB_APP/gnb_config.c | 38 +++++++++++++++++++- openair2/RRC/NR/nr_rrc_config.c | 30 ++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h index e5ed3aaf00..504b6a8ed5 100644 --- a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h +++ b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h @@ -65,6 +65,7 @@ int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { return(0 void fill_scc_sim(NR_ServingCellConfigCommon_t *scc,uint64_t *ssb_bitmap,int N_RB_DL,int N_RB_UL,int mu_dl,int mu_ul); void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap); void prepare_scc(NR_ServingCellConfigCommon_t *scc); +void prepare_msgA_scc(NR_ServingCellConfigCommon_t *scc); void prepare_scd(NR_ServingCellConfig_t *scd); uint32_t ngap_generate_gNB_id(void) {return 0;} diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index a528835b03..51913209c9 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -145,6 +145,28 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17)); } +void prepare_msgA_scc(NR_ServingCellConfigCommon_t *scc) { + NR_BWP_UplinkCommon_t *initialUplinkBWP = scc->uplinkConfigCommon->initialUplinkBWP; + // Add the struct ext1 + initialUplinkBWP->ext1 = calloc(1, sizeof(*initialUplinkBWP->ext1)); + initialUplinkBWP->ext1->msgA_ConfigCommon_r16 = calloc(1, sizeof(*initialUplinkBWP->ext1->msgA_ConfigCommon_r16)); + initialUplinkBWP->ext1->msgA_ConfigCommon_r16->present = NR_SetupRelease_MsgA_ConfigCommon_r16_PR_setup; + initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup = + calloc(1, sizeof(*initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup)); + NR_MsgA_ConfigCommon_r16_t *NR_MsgA_ConfigCommon_r16 = initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup; + NR_MsgA_ConfigCommon_r16->rach_ConfigCommonTwoStepRA_r16.rach_ConfigGenericTwoStepRA_r16.msgB_ResponseWindow_r16 = + calloc(1, sizeof(long)); + NR_MsgA_ConfigCommon_r16->rach_ConfigCommonTwoStepRA_r16.msgA_RSRP_Threshold_r16 = calloc(1, sizeof(NR_RSRP_Range_t)); + + NR_MsgA_ConfigCommon_r16->rach_ConfigCommonTwoStepRA_r16.msgA_CB_PreamblesPerSSB_PerSharedRO_r16 = calloc(1, sizeof(long)); + + NR_MsgA_ConfigCommon_r16->msgA_PUSCH_Config_r16 = calloc(1, sizeof(NR_MsgA_PUSCH_Config_r16_t)); + NR_MsgA_PUSCH_Config_r16_t *msgA_PUSCH_Config_r16 = NR_MsgA_ConfigCommon_r16->msgA_PUSCH_Config_r16; + msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16 = calloc(1, sizeof(NR_MsgA_PUSCH_Resource_r16_t)); + NR_MsgA_PUSCH_Resource_r16_t *msgA_PUSCH_Resource = msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16; + msgA_PUSCH_Resource->startSymbolAndLengthMsgA_PO_r16 = calloc(1, sizeof(long)); + msgA_PUSCH_Config_r16->msgA_TransformPrecoder_r16 = calloc(1, sizeof(long)); +} // Section 4.1 in 38.213 NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR get_ssb_len(NR_ServingCellConfigCommon_t *scc) @@ -384,6 +406,14 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap) scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing=NULL; } + if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 + && (int)scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->msgA_PUSCH_Config_r16 + ->msgA_PUSCH_ResourceGroupA_r16->msgA_PUSCH_TimeDomainOffset_r16 + == 0) { + free(scc->uplinkConfigCommon->initialUplinkBWP->ext1); + scc->uplinkConfigCommon->initialUplinkBWP->ext1 = NULL; + } + if ((int)*scc->n_TimingAdvanceOffset == -1) { free(scc->n_TimingAdvanceOffset); scc->n_TimingAdvanceOffset = NULL; @@ -935,14 +965,20 @@ static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cf uint64_t ssb_bitmap=0xff; prepare_scc(scc); paramdef_t SCCsParams[] = SCCPARAMS_DESC(scc); + prepare_msgA_scc(scc); + paramdef_t MsgASCCsParams[] = MSGASCCPARAMS_DESC(scc); paramlist_def_t SCCsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, NULL, 0}; + paramlist_def_t MsgASCCsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, NULL, 0}; char aprefix[MAX_OPTNAME_SIZE*2 + 8]; sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); config_getlist(cfg, &SCCsParamList, NULL, 0, aprefix); - if (SCCsParamList.numelt > 0) { + config_getlist(cfg, &MsgASCCsParamList, NULL, 0, aprefix); + + if (SCCsParamList.numelt > 0 || MsgASCCsParamList.numelt > 0) { sprintf(aprefix, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, 0); config_get(cfg, SCCsParams, sizeofArray(SCCsParams), aprefix); + config_get(cfg, MsgASCCsParams, sizeofArray(MsgASCCsParams), aprefix); struct NR_FrequencyInfoDL *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; LOG_I(RRC, "Read in ServingCellConfigCommon (PhysCellId %d, ABSFREQSSB %d, DLBand %d, ABSFREQPOINTA %d, DLBW " diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index e3f310a4c9..201a0e84d4 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -71,6 +71,25 @@ static NR_SetupRelease_RACH_ConfigCommon_t *clone_rach_configcommon(const NR_Set return clone; } +static NR_SetupRelease_MsgA_ConfigCommon_r16_t *clone_msga_configcommon(const NR_SetupRelease_MsgA_ConfigCommon_r16_t *mcc) +{ + if (mcc == NULL || mcc->present == NR_SetupRelease_MsgA_ConfigCommon_r16_PR_NOTHING) + return NULL; + NR_SetupRelease_MsgA_ConfigCommon_r16_t *clone = calloc_or_fail(1, sizeof(*clone)); + clone->present = mcc->present; + if (clone->present == NR_SetupRelease_MsgA_ConfigCommon_r16_PR_release) + return clone; + uint8_t buf[1024]; + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_MsgA_ConfigCommon_r16, NULL, mcc->choice.setup, buf, sizeof(buf)); + AssertFatal(enc_rval.encoded > 0 && enc_rval.encoded < sizeof(buf), + "could not clone NR_MsgA_ConfigCommon_r16: problem while encoding\n"); + asn_dec_rval_t dec_rval = + uper_decode(NULL, &asn_DEF_NR_MsgA_ConfigCommon_r16, (void **)&clone->choice.setup, buf, enc_rval.encoded, 0, 0); + AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed == enc_rval.encoded, + "could not clone NR_MsgA_ConfigCommon_r16:: problem while decoding\n"); + return clone; +} + static NR_SetupRelease_PUSCH_ConfigCommon_t *clone_pusch_configcommon(const NR_SetupRelease_PUSCH_ConfigCommon_t *pcc) { if (pcc == NULL || pcc->present == NR_SetupRelease_PUSCH_ConfigCommon_PR_NOTHING) @@ -2351,6 +2370,17 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, UL->initialUplinkBWP.genericParameters = clone_generic_parameters(&scc->uplinkConfigCommon->initialUplinkBWP->genericParameters); UL->initialUplinkBWP.rach_ConfigCommon = clone_rach_configcommon(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon); + + if (scc->uplinkConfigCommon->initialUplinkBWP->ext1) { + NR_SetupRelease_MsgA_ConfigCommon_r16_t *msgA_configcommon = + clone_msga_configcommon(scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16); + if (msgA_configcommon) { + // Add the struct ext1 + UL->initialUplinkBWP.ext1 = calloc(1, sizeof(*UL->initialUplinkBWP.ext1)); + UL->initialUplinkBWP.ext1->msgA_ConfigCommon_r16 = msgA_configcommon; + } + } + UL->initialUplinkBWP.pusch_ConfigCommon = clone_pusch_configcommon(scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon); free(UL->initialUplinkBWP.pusch_ConfigCommon->choice.setup->groupHoppingEnabledTransformPrecoding); UL->initialUplinkBWP.pusch_ConfigCommon->choice.setup->groupHoppingEnabledTransformPrecoding = NULL; From abb7439b8a337f00faa23dac16bdf75607a00d2e Mon Sep 17 00:00:00 2001 From: ndomingues Date: Tue, 14 May 2024 11:28:38 +0100 Subject: [PATCH 03/15] Compute RA 2-Step MsgB_RNTI as specified in 3GPP TS 38.321 Section 5.1.3a --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 9 +++++++++ openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 3f0db0e4da..5d727dc883 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -5312,6 +5312,15 @@ rnti_t nr_get_ra_rnti(uint8_t s_id, uint8_t t_id, uint8_t f_id, uint8_t ul_carri return ra_rnti; } +rnti_t nr_get_MsgB_rnti(uint8_t s_id, uint8_t t_id, uint8_t f_id, uint8_t ul_carrier_id) +{ + // 3GPP TS 38.321 Section 5.1.3a + rnti_t MsgB_rnti = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id + 17920; + LOG_D(MAC, "f_id %d t_id %d s_id %d ul_carrier_id %d Computed MsgB_RNTI is 0x%04X\n", f_id, t_id, s_id, ul_carrier_id, MsgB_rnti); + + return MsgB_rnti; +} + int get_FeedbackDisabled(NR_DownlinkHARQ_FeedbackDisabled_r17_t *downlinkHARQ_FeedbackDisabled_r17, int harq_pid) { if (downlinkHARQ_FeedbackDisabled_r17 == NULL) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 4ce1571390..8290aaa1de 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -317,6 +317,8 @@ uint32_t compute_PDU_length(uint32_t num_TLV, uint32_t total_length); rnti_t nr_get_ra_rnti(uint8_t s_id, uint8_t t_id, uint8_t f_id, uint8_t ul_carrier_id); +rnti_t nr_get_MsgB_rnti(uint8_t s_id, uint8_t t_id, uint8_t f_id, uint8_t ul_carrier_id); + bool supported_bw_comparison(int bw_mhz, NR_SupportedBandwidth_t *supported_BW, long *support_90mhz); int get_FeedbackDisabled(NR_DownlinkHARQ_FeedbackDisabled_r17_t *downlinkHARQ_FeedbackDisabled_r17, int harq_pid); From 9d84ba7fbfb8a27d03751ec84feac9332d007b3e Mon Sep 17 00:00:00 2001 From: ndomingues Date: Tue, 14 May 2024 11:29:29 +0100 Subject: [PATCH 04/15] Refactor enum nr_ra_type_t and make it common for both gNB and UE --- openair2/LAYER2/NR_MAC_COMMON/nr_mac.h | 6 ++++ openair2/LAYER2/NR_MAC_UE/mac_defs.h | 9 ++---- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 30 ++++++++++++++------ 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index 1dff70618e..19db7e6818 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -560,6 +560,7 @@ typedef struct NR_UE_UL_BWP { uint16_t BWPSize; uint16_t BWPStart; NR_RACH_ConfigCommon_t *rach_ConfigCommon; + NR_MsgA_ConfigCommon_r16_t *msgA_ConfigCommon_r16; NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList_Common; NR_ConfiguredGrantConfig_t *configuredGrantConfig; NR_PUSCH_Config_t *pusch_Config; @@ -630,5 +631,10 @@ typedef struct NR_tda_info { bool valid_tda; } NR_tda_info_t; +typedef enum { + RA_4_STEP = 0, + RA_2_STEP = 1, +} nr_ra_type_t; + #endif /*__LAYER2_MAC_H__ */ diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index c913321f80..8eb6b194dc 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -191,11 +191,6 @@ typedef enum { RE_ESTABLISHMENT } NR_UE_MAC_reset_cause_t; -typedef enum { - RA_2STEP = 0, - RA_4STEP -} nr_ra_type_e; - typedef struct { // after multiplexing buffer remain for each lcid int32_t LCID_buffer_remain; @@ -299,7 +294,7 @@ typedef struct { /// uint8_t RA_SCALING_FACTOR_BI; /// Indicating whether it is 2-step or 4-step RA - nr_ra_type_e RA_TYPE; + nr_ra_type_t RA_TYPE; /// UE configured maximum output power int RA_PCMAX; } NR_PRACH_RESOURCES_t; @@ -312,6 +307,8 @@ typedef struct { nrRA_UE_state_t ra_state; /// RA contention type uint8_t cfra; + /// RA type + nr_ra_type_t ra_type; /// RA rx frame offset: compensate RA rx offset introduced by OAI gNB. uint8_t RA_offset; /// RA-rnti diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 6272c4c33f..eadc1677f4 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -104,15 +104,19 @@ void init_RA(NR_UE_MAC_INST_t *mac, prach_resources->POWER_OFFSET_2STEP_RA = 0; prach_resources->RA_SCALING_FACTOR_BI = 1; + + // Contention Free if (rach_ConfigDedicated) { if (rach_ConfigDedicated->cfra){ - LOG_I(NR_MAC, "Initialization of 2-step contention-free random access procedure\n"); - prach_resources->RA_TYPE = RA_2STEP; + LOG_I(MAC, "Initialization of 4-Step CFRA procedure\n"); + prach_resources->RA_TYPE = RA_4_STEP; + ra->ra_type = RA_4_STEP; ra->cfra = 1; } else if (rach_ConfigDedicated->ext1){ - if (rach_ConfigDedicated->ext1->cfra_TwoStep_r16){ - LOG_I(NR_MAC, "Setting RA type to 2-step...\n"); - prach_resources->RA_TYPE = RA_2STEP; + if (rach_ConfigDedicated->ext1->cfra_TwoStep_r16) { + LOG_I(MAC, "Initialization of 2-Step CFRA procedure\n"); + prach_resources->RA_TYPE = RA_2_STEP; + ra->ra_type = RA_2_STEP; ra->cfra = 1; } else { LOG_E(NR_MAC, "Config not handled\n"); @@ -120,10 +124,20 @@ void init_RA(NR_UE_MAC_INST_t *mac, } else { LOG_E(NR_MAC, "Config not handled\n"); } - } else { - LOG_I(NR_MAC, "Initialization of 4-step contention-based random access procedure\n"); - prach_resources->RA_TYPE = RA_4STEP; + // Contention Based + } else if (mac->current_UL_BWP->msgA_ConfigCommon_r16) { + LOG_I(MAC, "Initialization of 2-Step CBRA procedure\n"); + prach_resources->RA_TYPE = RA_2_STEP; + ra->ra_type = RA_2_STEP; ra->cfra = 0; + } else if (nr_rach_ConfigCommon) { + LOG_I(MAC, "Initialization of 4-Step CBRA procedure\n"); + prach_resources->RA_TYPE = RA_4_STEP; + ra->ra_type = RA_4_STEP; + ra->cfra = 0; + } else { + LOG_E(MAC, "Config not handled\n"); + AssertFatal(false, "In %s: config not handled\n", __FUNCTION__); } switch (rach_ConfigGeneric->powerRampingStep){ // in dB From c4b51b78d6edb72938c4c6fea8097d7d9d71129b Mon Sep 17 00:00:00 2001 From: ndomingues Date: Tue, 14 May 2024 11:30:02 +0100 Subject: [PATCH 05/15] Decode msgA_ConfigCommon_r16 from received SIB1 at UE and save it in bwp->msgA_ConfigCommon_r16 --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index de8fa49d48..64adaabd79 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -1540,6 +1540,12 @@ static void configure_common_BWP_ul(NR_UE_MAC_INST_t *mac, int bwp_id, NR_BWP_Up NR_RACH_ConfigCommon_t, asn_DEF_NR_RACH_ConfigCommon); } + if (ul_common->ext1 && ul_common->ext1->msgA_ConfigCommon_r16) { + HANDLE_SETUPRELEASE_DIRECT(bwp->msgA_ConfigCommon_r16, + ul_common->ext1->msgA_ConfigCommon_r16, + NR_MsgA_ConfigCommon_r16_t, + asn_DEF_NR_MsgA_ConfigCommon_r16); + } if (ul_common->pucch_ConfigCommon) HANDLE_SETUPRELEASE_DIRECT(bwp->pucch_ConfigCommon, ul_common->pucch_ConfigCommon, From 3083f4f3d1e98df49cdeae46ff6e7a9b0e968ab8 Mon Sep 17 00:00:00 2001 From: ndomingues Date: Tue, 14 May 2024 11:33:18 +0100 Subject: [PATCH 06/15] Common parameters to apply successRAR --- openair2/LAYER2/NR_MAC_COMMON/nr_mac.h | 56 +++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index 19db7e6818..fd042441d9 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -244,6 +244,12 @@ typedef struct { uint8_t E: 1; } __attribute__ ((__packed__)) NR_RA_HEADER_RAPID; +typedef struct { + uint8_t RAPID: 6; + uint8_t T1: 1; + uint8_t E: 1; +} __attribute__((__packed__)) NR_RA_HEADER_RAPID_MSGB; + /*!\brief RAR MAC subheader with Backoff Indicator */ typedef struct { uint8_t BI: 4; @@ -252,7 +258,23 @@ typedef struct { uint8_t E: 1; } __attribute__ ((__packed__)) NR_RA_HEADER_BI; -// TS 38.321 ch. 6.2.3 +typedef struct { + uint8_t BI: 4; + uint8_t R: 1; + uint8_t T2: 1; + uint8_t T1: 1; + uint8_t E: 1; +} __attribute__((__packed__)) NR_RA_HEADER_BI_MSGB; + +typedef struct { + uint8_t R: 4; + uint8_t S: 1; + uint8_t T2: 1; + uint8_t T1: 1; + uint8_t E: 1; +} __attribute__((__packed__)) NR_RA_HEADER_SUCCESS_RAR_MSGB; + +// TS 38.321 Sec. 6.2.3 typedef struct { uint8_t TA1: 7; // octet 1 [6:0] uint8_t R: 1; // octet 1 [7] @@ -265,6 +287,38 @@ typedef struct { uint8_t TCRNTI_2: 8; // octet 7 [7:0] } __attribute__ ((__packed__)) NR_MAC_RAR; +// TS 38.321 Sec. 6.2.3 +typedef struct { + uint8_t TA1: 7; // octet 1 [6:0] + uint8_t R: 1; // octet 1 [7] + uint8_t UL_GRANT_1: 3; // octet 2 [2:0] + uint8_t TA2: 5; // octet 2 [7:3] + uint8_t UL_GRANT_2: 8; // octet 3 [7:0] + uint8_t UL_GRANT_3: 8; // octet 4 [7:0] + uint8_t UL_GRANT_4: 8; // octet 5 [7:0] + uint8_t TCRNTI_1: 8; // octet 6 [7:0] + uint8_t TCRNTI_2: 8; // octet 7 [7:0] +} __attribute__((__packed__)) NR_MAC_RAR_MSGB; + +// TS 38.321 Sec. 6.2.3 +typedef struct { + uint8_t CONT_RES_1: 8; // octet 1 [7:0] + uint8_t CONT_RES_2: 8; // octet 2 [7:0] + uint8_t CONT_RES_3: 8; // octet 3 [7:0] + uint8_t CONT_RES_4: 8; // octet 4 [7:0] + uint8_t CONT_RES_5: 8; // octet 5 [7:0] + uint8_t CONT_RES_6: 8; // octet 6 [7:0] + uint8_t HARQ_FTI: 3; // octet 7 [2:0] + uint8_t TPC: 2; // octet 7 [4:3] + uint8_t CH_ACESS_CPEXT: 2; // octet 7 [6:5] + uint8_t R: 1; // octet 7 [7] + uint8_t TA1: 4; // octet 8 [3:0] + uint8_t PUCCH_RI: 4; // octet 8 [7:4] + uint8_t TA2: 8; // octet 9 [7:0] + uint8_t CRNTI_1: 8; // octet 10 [7:0] + uint8_t CRNTI_2: 8; // octet 11 [7:0] +} __attribute__((__packed__)) NR_MAC_SUCCESS_RAR; + // DCI pdu structures. Used by both gNB and UE. typedef struct { uint32_t val; From c609dd8fcfee3c396fd591602dbb3221ed69dbb5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 1 Oct 2024 16:16:19 +0200 Subject: [PATCH 07/15] Implement common nr_get_mu() in nr_mac_common These functions look up the numerology, and code can be harmonized: - ssb_index_from_prach() - find_SSB_and_RO_available() - schedule_nr_prach() The next commits also need to look up the numerology from the UplinkConfigCommon. This provides the common implementation to be used in follow-up commits. --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 26 +++++++++++++++++++ openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 2 ++ openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 20 ++++---------- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 5d727dc883..cbdcb51d22 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -5331,3 +5331,29 @@ int get_FeedbackDisabled(NR_DownlinkHARQ_FeedbackDisabled_r17_t *downlinkHARQ_Fe return (downlinkHARQ_FeedbackDisabled_r17->buf[byte_index] >> (7 - bit_index)) & 1; } + +int nr_get_mu(const NR_UplinkConfigCommon_t *uplinkConfigCommon) +{ + int mu; + NR_BWP_UplinkCommon_t *initialUplinkBWP = uplinkConfigCommon->initialUplinkBWP; + + // if 2-Step configuration file exists + if (initialUplinkBWP->ext1 && initialUplinkBWP->ext1->msgA_ConfigCommon_r16) { + if (initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->rach_ConfigCommonTwoStepRA_r16.msgA_SubcarrierSpacing_r16) { + // Choose Subcarrier Spacing of configuration file of 2-Step + const NR_MsgA_ConfigCommon_r16_t *msgacc = initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup; + mu = *msgacc->rach_ConfigCommonTwoStepRA_r16.msgA_SubcarrierSpacing_r16; + } else { + // Choose Subcarrier Spacing of configuration file of 4-Step + mu = uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + } + } else { + if (initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) { + mu = *initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing; + } else { + mu = uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + } + } + + return mu; +} diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 8290aaa1de..990e91db65 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -327,4 +327,6 @@ int get_nrofHARQ_ProcessesForPDSCH(const NR_UE_ServingCell_Info_t *sc_info); int get_nrofHARQ_ProcessesForPUSCH(const NR_UE_ServingCell_Info_t *sc_info); +int nr_get_mu(const NR_UplinkConfigCommon_t *uplinkConfigCommon); + #endif diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index ed32fe3669..5c19a3de99 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -91,16 +91,13 @@ static int16_t ssb_index_from_prach(module_id_t module_idP, float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value]; uint16_t start_symbol_index = 0; - uint8_t mu,N_dur=0,N_t_slot=0,start_symbol = 0, temp_start_symbol = 0, N_RA_slot=0; + uint8_t N_dur=0,N_t_slot=0,start_symbol = 0, temp_start_symbol = 0, N_RA_slot=0; uint16_t format,RA_sfn_index = -1; uint8_t config_period = 1; uint16_t prach_occasion_id = -1; uint8_t num_active_ssb = cc->num_active_ssb; - if (rach_ConfigCommon->msg1_SubcarrierSpacing) - mu = *rach_ConfigCommon->msg1_SubcarrierSpacing; - else - mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + int mu = nr_get_mu(scc->uplinkConfigCommon); get_nr_prach_info_from_index(config_index, (int)frameP, @@ -167,7 +164,7 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac) nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0]; NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; uint8_t config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; - uint8_t mu,N_dur=0,N_t_slot=0,start_symbol=0,N_RA_slot = 0; + uint8_t N_dur=0,N_t_slot=0,start_symbol=0,N_RA_slot = 0; uint16_t format,N_RA_sfn = 0,unused_RA_occasion,repetition = 0; uint8_t num_active_ssb = 0; uint8_t max_association_period = 1; @@ -204,10 +201,7 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac) break; } - if (rach_ConfigCommon->msg1_SubcarrierSpacing) - mu = *rach_ConfigCommon->msg1_SubcarrierSpacing; - else - mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + int mu = nr_get_mu(scc->uplinkConfigCommon); // prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4 get_nr_prach_occasion_info_from_index(config_index, @@ -267,11 +261,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP NR_COMMON_channels_t *cc = gNB->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - int mu; - if (rach_ConfigCommon->msg1_SubcarrierSpacing) - mu = *rach_ConfigCommon->msg1_SubcarrierSpacing; - else - mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + int mu = nr_get_mu(scc->uplinkConfigCommon); int index = ul_buffer_index(frameP, slotP, mu, gNB->UL_tti_req_ahead_size); nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[0][index]; nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0]; From cbbbeb80511757e110addd896783efdb04c0a0ff Mon Sep 17 00:00:00 2001 From: ndomingues Date: Tue, 14 May 2024 11:30:33 +0100 Subject: [PATCH 08/15] Baseline implementation of RA 2-Step MsgA procedures at gNB --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 168 ++++++++++++++++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 41 +++-- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 19 +- 3 files changed, 189 insertions(+), 39 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 5c19a3de99..3ffeb22228 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -250,8 +250,114 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac) cc->max_association_period, N_RA_sfn, cc->total_prach_occasions_per_config_period); -} - +} + +static void schedule_nr_MsgA_pusch(NR_UplinkConfigCommon_t *uplinkConfigCommon, + gNB_MAC_INST *nr_mac, + module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_prach_pdu_t *prach_pdu, + uint16_t dmrs_TypeA_Position, + NR_PhysCellId_t physCellId) +{ + NR_SCHED_ENSURE_LOCKED(&nr_mac->sched_lock); + + NR_MsgA_PUSCH_Resource_r16_t *msgA_PUSCH_Resource = uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice + .setup->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16; + + int mu = nr_get_mu(uplinkConfigCommon); + + const int n_slots_frame = nr_slots_per_frame[mu]; + slot_t msgA_pusch_slot = (slotP + msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16) % n_slots_frame; + frame_t msgA_pusch_frame = (frameP + ((slotP + msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16) / n_slots_frame)) % 1024; + + int index = ul_buffer_index((int)msgA_pusch_frame, (int)msgA_pusch_slot, mu, nr_mac->UL_tti_req_ahead_size); + nfapi_nr_ul_tti_request_t *UL_tti_req = &nr_mac[module_idP].UL_tti_req_ahead[0][index]; + + UL_tti_req->SFN = msgA_pusch_frame; + UL_tti_req->Slot = msgA_pusch_slot; + AssertFatal(is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[msgA_pusch_slot / 64], msgA_pusch_slot), + "Slot %d is not an Uplink slot, invalid msgA_PUSCH_TimeDomainOffset_r16 %ld\n", + msgA_pusch_slot, + msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16); + + UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; + UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); + nfapi_nr_pusch_pdu_t *pusch_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].pusch_pdu; + memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); + + rnti_t ra_rnti = nr_get_ra_rnti(prach_pdu->prach_start_symbol, slotP, prach_pdu->num_ra, 0); + + // Fill PUSCH PDU + pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; + pusch_pdu->rnti = ra_rnti; + pusch_pdu->handle = 0; + pusch_pdu->rb_size = msgA_PUSCH_Resource->nrofPRBs_PerMsgA_PO_r16; + pusch_pdu->mcs_table = 0; + pusch_pdu->frequency_hopping = + msgA_PUSCH_Resource->msgA_IntraSlotFrequencyHopping_r16 ? *msgA_PUSCH_Resource->msgA_IntraSlotFrequencyHopping_r16 : 0; + pusch_pdu->dmrs_ports = 1; // 6.2.2 in 38.214 only port 0 to be used + AssertFatal(msgA_PUSCH_Resource->startSymbolAndLengthMsgA_PO_r16, + "Only SLIV based on startSymbolAndLengthMsgA_PO_r16 implemented\n"); + int S = 0; + int L = 0; + SLIV2SL(*msgA_PUSCH_Resource->startSymbolAndLengthMsgA_PO_r16, &S, &L); + pusch_pdu->start_symbol_index = S; + pusch_pdu->nr_of_symbols = L; + pusch_pdu->pusch_data.new_data_indicator = 1; + pusch_pdu->nrOfLayers = 1; + pusch_pdu->num_dmrs_cdm_grps_no_data = 2; // no data in dmrs symbols as in 6.2.2 in 38.214 + pusch_pdu->ul_dmrs_symb_pos = get_l_prime(3, 0, pusch_dmrs_pos2, pusch_len1, 10, dmrs_TypeA_Position); + pusch_pdu->transform_precoding = *uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->msgA_PUSCH_Config_r16->msgA_TransformPrecoder_r16; + pusch_pdu->rb_bitmap[0] = 0; + pusch_pdu->rb_start = msgA_PUSCH_Resource->frequencyStartMsgA_PUSCH_r16; // rb_start depends on the RO + int locationAndBandwidth = uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth; + pusch_pdu->bwp_size = NRRIV2BW(locationAndBandwidth, MAX_BWP_SIZE); + pusch_pdu->bwp_start = NRRIV2PRBOFFSET(locationAndBandwidth, MAX_BWP_SIZE); + pusch_pdu->subcarrier_spacing = 0; + pusch_pdu->cyclic_prefix = 0; + pusch_pdu->uplink_frequency_shift_7p5khz = 0; + pusch_pdu->vrb_to_prb_mapping = 0; + pusch_pdu->dmrs_config_type = 0; + pusch_pdu->data_scrambling_id = 0; + if (msgA_PUSCH_Resource->msgA_DMRS_Config_r16.msgA_ScramblingID0_r16) { + pusch_pdu->ul_dmrs_scrambling_id = *msgA_PUSCH_Resource->msgA_DMRS_Config_r16.msgA_ScramblingID0_r16; + } else { + pusch_pdu->ul_dmrs_scrambling_id = physCellId; + } + pusch_pdu->scid = + 0; // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1]. Should match what is sent in DCI 0_1, otherwise set to 0. + pusch_pdu->pusch_identity = 0; + pusch_pdu->resource_alloc = 1; // type 1 + pusch_pdu->tx_direct_current_location = 0; + pusch_pdu->mcs_index = msgA_PUSCH_Resource->msgA_MCS_r16; + pusch_pdu->qam_mod_order = nr_get_Qm_dl(pusch_pdu->mcs_index, pusch_pdu->mcs_table); + + int num_dmrs_symb = 0; + for (int i = 10; i < 10 + 3; i++) + num_dmrs_symb += (pusch_pdu->ul_dmrs_symb_pos >> i) & 1; + AssertFatal(pusch_pdu->mcs_index <= 28, "Exceeding MCS limit for MsgA PUSCH\n"); + int R = nr_get_code_rate_ul(pusch_pdu->mcs_index, pusch_pdu->mcs_table); + pusch_pdu->target_code_rate = R; + int TBS = nr_compute_tbs(pusch_pdu->qam_mod_order, + R, + pusch_pdu->rb_size, + pusch_pdu->nr_of_symbols, + num_dmrs_symb * 12, // nb dmrs set for no data in dmrs symbol + 0, // nb_rb_oh + 0, // to verify tb scaling + pusch_pdu->nrOfLayers) + >> 3; + + pusch_pdu->pusch_data.tb_size = TBS; + pusch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS << 3, R); + + LOG_D(NR_MAC, "Scheduling MsgA PUSCH in %d.%d\n", msgA_pusch_frame, msgA_pusch_slot); + + UL_tti_req->n_pdus += 1; +} + void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { gNB_MAC_INST *gNB = RC.nrmac[module_idP]; @@ -416,6 +522,18 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP AssertFatal(1==0,"Invalid PRACH format"); } } + if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 + && scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16) { + if (gNB->UE_info.list[0] == NULL) + schedule_nr_MsgA_pusch(scc->uplinkConfigCommon, + gNB, + module_idP, + frameP, + slotP, + prach_pdu, + scc->dmrs_TypeA_Position, + *scc->physCellId); + } } } } @@ -524,18 +642,27 @@ void nr_initiate_ra_proc(module_id_t module_idP, ra->rnti = trial; } - ra->ra_state = nrRA_Msg2; ra->preamble_frame = frameP; ra->preamble_slot = slotP; ra->preamble_index = preamble_index; ra->timing_offset = timing_offset; uint8_t ul_carrier_id = 0; // 0 for NUL 1 for SUL ra->RA_rnti = nr_get_ra_rnti(symbol, slotP, freq_index, ul_carrier_id); + + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 && scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16) { + ra->ra_type = RA_2_STEP; + ra->ra_state = nrRA_WAIT_MsgA_PUSCH; + ra->MsgB_rnti = nr_get_MsgB_rnti(symbol, slotP, freq_index, ul_carrier_id); + } else { + ra->ra_type = RA_4_STEP; + ra->ra_state = nrRA_Msg2; + } + int index = ra - cc->ra; LOG_I(NR_MAC, "%d.%d UE RA-RNTI %04x TC-RNTI %04x: Activating RA process index %d\n", frameP, slotP, ra->RA_rnti, ra->rnti, index); // Configure RA BWP - NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; configure_UE_BWP(nr_mac, scc, NULL, ra, NULL, -1, -1); uint8_t beam_index = ssb_index_from_prach(module_idP, frameP, slotP, preamble_index, freq_index, symbol); @@ -1742,18 +1869,18 @@ static void nr_generate_Msg4(module_id_t module_idP, // if it is a DL slot, if the RA is in MSG4 state if (is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slotP / 64], slotP)) { - NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - NR_SearchSpace_t *ss = ra->ra_ss; + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + NR_SearchSpace_t *ss = ra->ra_ss; - NR_ControlResourceSet_t *coreset = ra->coreset; - AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg4\n"); + NR_ControlResourceSet_t *coreset = ra->coreset; + AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg4\n"); - uint16_t mac_sdu_length = 0; + uint16_t mac_sdu_length = 0; - NR_UE_info_t *UE = find_nr_UE(&nr_mac->UE_info, ra->rnti); - if (!UE) { - LOG_E(NR_MAC, "want to generate Msg4, but rnti %04x not in the table\n", ra->rnti); - return; + NR_UE_info_t *UE = find_nr_UE(&nr_mac->UE_info, ra->rnti); + if (!UE) { + LOG_E(NR_MAC, "want to generate Msg4, but rnti %04x not in the table\n", ra->rnti); + return; } NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; @@ -1961,9 +2088,20 @@ static void nr_generate_Msg4(module_id_t module_idP, memcpy(&buf[mac_pdu_length + mac_subheader_len], buffer, mac_sdu_length); } + rnti_t rnti = ra->ra_type == RA_4_STEP ? ra->rnti : ra->MsgB_rnti; + const int pduindex = nr_mac->pdu_index[CC_id]++; prepare_dl_pdus(nr_mac, ra, dl_bwp, dl_req, pucch, dmrs_info, msg4_tda, aggregation_level, CCEIndex, tb_size, harq->ndi, sched_ctrl->tpc1, delta_PRI, - current_harq_pid, time_domain_assignment, CC_id, ra->rnti, harq->round, mcsIndex, tb_scaling, pduindex, rbStart, rbSize); + current_harq_pid, + time_domain_assignment, + CC_id, + rnti, + harq->round, + mcsIndex, + tb_scaling, + pduindex, + rbStart, + rbSize); // Add padding header and zero rest out if there is space left if (ra->mac_pdu_length < harq->tb_size) { @@ -2208,7 +2346,7 @@ void nr_schedule_RA(module_id_t module_idP, LOG_D(NR_MAC, "RA[state:%d]\n", ra->ra_state); // Check RA Contention Resolution timer - if (ra->ra_state >= nrRA_WAIT_Msg3) { + if (ra->ra_type == RA_4_STEP && ra->ra_state >= nrRA_WAIT_Msg3) { ra->contention_resolution_timer--; if (ra->contention_resolution_timer < 0) { LOG_W(NR_MAC, "(%d.%d) RA Contention Resolution timer expired for UE 0x%04x, RA procedure failed...\n", frameP, slotP, ra->rnti); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index cb233eae1b..234420f39d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -596,7 +596,7 @@ void handle_nr_ul_harq(const int CC_idP, } } NR_SCHED_UNLOCK(&nrmac->sched_lock); - LOG_E(NR_MAC, "no RA proc for RNTI 0x%04x in Msg3/PUSCH\n", crc_pdu->rnti); + LOG_D(NR_MAC, "no RA proc for RNTI 0x%04x in Msg3/MsgA-PUSCH\n", crc_pdu->rnti); return; } if (nrmac->radio_config.disable_harq) { @@ -819,7 +819,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, * it. */ for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) { NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i]; - if (ra->ra_state != nrRA_WAIT_Msg3) + if (ra->ra_type == RA_4_STEP && ra->ra_state != nrRA_WAIT_Msg3) continue; if (no_sig) { @@ -827,22 +827,29 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, handle_msg3_failed_rx(ra, i, gNB_mac->ul_bler.harq_round_max); continue; } - - // random access pusch with TC-RNTI - if (ra->rnti != current_rnti) { - LOG_D(NR_MAC, "expected TC_RNTI %04x to match current RNTI %04x\n", ra->rnti, current_rnti); - - if ((frameP == ra->Msg3_frame) && (slotP == ra->Msg3_slot)) { - LOG_W(NR_MAC, - "Random Access %i failed at state %s (TC_RNTI %04x RNTI %04x)\n", - i, - nrra_text[ra->ra_state], - ra->rnti, - current_rnti); - nr_clear_ra_proc(ra); + if (ra->ra_type == RA_2_STEP) { + // random access pusch with RA-RNTI + if (ra->RA_rnti != current_rnti) { + LOG_E(NR_MAC, "expected TC_RNTI %04x to match current RNTI %04x\n", ra->RA_rnti, current_rnti); + continue; } + } else { + // random access pusch with TC-RNTI + if (ra->rnti != current_rnti) { + LOG_E(NR_MAC, "expected TC_RNTI %04x to match current RNTI %04x\n", ra->rnti, current_rnti); - continue; + if ((frameP == ra->Msg3_frame) && (slotP == ra->Msg3_slot)) { + LOG_W(NR_MAC, + "Random Access %i failed at state %s (TC_RNTI %04x RNTI %04x)\n", + i, + nrra_text[ra->ra_state], + ra->rnti, + current_rnti); + nr_clear_ra_proc(ra); + } + + continue; + } } UE = UE ? UE : add_new_nr_ue(gNB_mac, ra->rnti, ra->CellGroup); @@ -882,7 +889,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, ra->CellGroup->rlc_BearerToAddModList); nr_clear_ra_proc(ra); } else { - LOG_D(NR_MAC, "[RAPROC] Received Msg3:\n"); + LOG_D(NR_MAC, "[RAPROC] Received %s:\n", ra->ra_type == RA_2_STEP ? "MsgA-PUSCH" : "Msg3"); for (uint32_t k = 0; k < sdu_lenP; k++) { LOG_D(NR_MAC, "(%i): 0x%x\n", k, sduP[k]); } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 1306652033..556d30f3fd 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -114,16 +114,18 @@ typedef struct { } NR_list_t; typedef enum { - nrRA_gNB_IDLE = 0, - nrRA_Msg2 = 1, - nrRA_WAIT_Msg3 = 2, - nrRA_Msg3_retransmission = 3, - nrRA_Msg4 = 4, - nrRA_WAIT_Msg4_ACK = 5, + nrRA_gNB_IDLE, + nrRA_Msg2, + nrRA_WAIT_MsgA_PUSCH, + nrRA_WAIT_Msg3, + nrRA_Msg3_retransmission, + nrRA_Msg4, + nrRA_MsgB, + nrRA_WAIT_Msg4_ACK, } RA_gNB_state_t; static const char *const nrra_text[] = - {"IDLE", "Msg2", "WAIT_Msg3", "Msg3_retransmission", "Msg3_dcch_dtch", "Msg4", "WAIT_Msg4_ACK"}; + {"IDLE", "Msg2", "WAIT_MsgA_PUSCH", "WAIT_Msg3", "Msg3_retransmission", "Msg3_dcch_dtch", "Msg4", "MsgB", "WAIT_Msg4_ACK"}; typedef struct { int idx; @@ -219,6 +221,8 @@ typedef struct { rnti_t rnti; /// RA RNTI allocated from received PRACH uint16_t RA_rnti; + /// MsgB RNTI allocated from received MsgA + uint16_t MsgB_rnti; /// Received UE Contention Resolution Identifier uint8_t cont_res_id[6]; /// Msg3 first RB @@ -247,6 +251,7 @@ typedef struct { /// Preambles for contention-free access NR_preamble_ue_t preambles; int contention_resolution_timer; + nr_ra_type_t ra_type; /// CFRA flag bool cfra; // BWP for RA From 160210ebae4525df5c871c0b222dc903cbd95f56 Mon Sep 17 00:00:00 2001 From: ndomingues Date: Tue, 14 May 2024 11:31:40 +0100 Subject: [PATCH 09/15] Baseline implementation of RA 2-Step MsgA procedures at UE --- openair1/PHY/NR_UE_TRANSPORT/nr_prach.c | 4 +- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 21 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 10 +- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 197 ++++++++++++++----- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 125 +++++++++++- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 2 +- 6 files changed, 288 insertions(+), 71 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index 471b2aee38..e2928b2df4 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -225,7 +225,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t k += kbar; k *= 2; - LOG_I(PHY, "PRACH [UE %d] in frame.slot %d.%d, placing PRACH in position %d, msg1 frequency start %d (k1 %d), preamble_offset %d, first_nonzero_root_idx %d\n", + LOG_I(PHY, + "PRACH [UE %d] in frame.slot %d.%d, placing PRACH in position %d, Msg1/MsgA-Preamble frequency start %d (k1 %d), " + "preamble_offset %d, first_nonzero_root_idx %d\n", Mod_id, frame, slot, diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 8eb6b194dc..9006c84be2 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -263,16 +263,17 @@ typedef struct { } NR_UE_SCHEDULING_INFO; typedef enum { - nrRA_UE_IDLE = 0, - nrRA_GENERATE_PREAMBLE = 1, - nrRA_WAIT_RAR = 2, - nrRA_WAIT_CONTENTION_RESOLUTION = 3, - nrRA_SUCCEEDED = 4, - nrRA_FAILED = 5 + nrRA_UE_IDLE, + nrRA_GENERATE_PREAMBLE, + nrRA_WAIT_RAR, + nrRA_WAIT_MSGB, + nrRA_WAIT_CONTENTION_RESOLUTION, + nrRA_SUCCEEDED, + nrRA_FAILED, } nrRA_UE_state_t; static const char *const nrra_ue_text[] = - {"UE_IDLE", "GENERATE_PREAMBLE", "WAIT_RAR", "WAIT_CONTENTION_RESOLUTION", "RA_SUCCEEDED", "RA_FAILED"}; + {"UE_IDLE", "GENERATE_PREAMBLE", "WAIT_RAR", "WAIT_MSGB", "WAIT_CONTENTION_RESOLUTION", "RA_SUCCEEDED", "RA_FAILED"}; typedef struct { /// PRACH format retrieved from prach_ConfigIndex @@ -311,8 +312,10 @@ typedef struct { nr_ra_type_t ra_type; /// RA rx frame offset: compensate RA rx offset introduced by OAI gNB. uint8_t RA_offset; - /// RA-rnti - uint16_t ra_rnti; + /// RA-RNTI + rnti_t ra_rnti; + /// MsgB-RNTI + rnti_t MsgB_rnti; /// Temporary CRNTI uint16_t t_crnti; /// number of attempt for rach diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 1f53812dec..6feca8756e 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -304,6 +304,10 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame_t frame, const int slot); +int16_t nr_get_RA_window_2Step(const NR_MsgA_ConfigCommon_r16_t *msgA_ConfigCommon_r16); + +int16_t nr_get_RA_window_4Step(const NR_RACH_ConfigCommon_t *rach_ConfigCommon); + void nr_get_RA_window(NR_UE_MAC_INST_t *mac); /* \brief Function called by PHY to retrieve information to be transmitted using the RA procedure. @@ -331,7 +335,7 @@ void nr_get_prach_resources(NR_UE_MAC_INST_t *mac, NR_PRACH_RESOURCES_t *prach_resources, NR_RACH_ConfigDedicated_t * rach_ConfigDedicated); -void prepare_msg4_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack); +void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack); void configure_initial_pucch(PUCCH_sched_t *pucch, int res_ind); void release_PUCCH_SRS(NR_UE_MAC_INST_t *mac); void nr_ue_reset_sync_state(NR_UE_MAC_INST_t *mac); @@ -356,7 +360,7 @@ void schedule_RA_after_SR_failure(NR_UE_MAC_INST_t *mac); void nr_Msg1_transmitted(NR_UE_MAC_INST_t *mac); void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id); void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac); -void nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max); +void nr_get_Msg3_MsgA_PUSCH_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max); void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac); int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu, @@ -410,7 +414,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *dci, csi_payload_t *csi_report, RAR_grant_t *rar_grant, - uint16_t rnti, + rnti_t rnti, int ss_type, const nr_dci_format_t dci_format); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index eadc1677f4..da183b3b14 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -191,10 +191,28 @@ void init_RA(NR_UE_MAC_INST_t *mac, break; } - if (nr_rach_ConfigCommon->ext1) { - if (nr_rach_ConfigCommon->ext1->ra_PrioritizationForAccessIdentity_r16){ + if (ra->ra_type == RA_2_STEP) { + if (nr_rach_ConfigCommon->ext1 && nr_rach_ConfigCommon->ext1->ra_PrioritizationForAccessIdentity_r16) { LOG_D(MAC, "Missing implementation for Access Identity initialization procedures\n"); } + // Perform initialization of variables specific to Random Access type as specified in clause 5.1.1a of TS 38.321 + NR_RACH_ConfigGenericTwoStepRA_r16_t nr_ra_ConfigGenericTwoStepRA_r16 = + mac->current_UL_BWP->msgA_ConfigCommon_r16->rach_ConfigCommonTwoStepRA_r16.rach_ConfigGenericTwoStepRA_r16; + // Takes the value of 2-Step RA variable + if (nr_ra_ConfigGenericTwoStepRA_r16.msgA_PreamblePowerRampingStep_r16) { + prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = *nr_ra_ConfigGenericTwoStepRA_r16.msgA_PreamblePowerRampingStep_r16; + } else { + // If 2-Step variable does not exist, it takes the value of 4-Step RA variable + prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = nr_rach_ConfigCommon->rach_ConfigGeneric.powerRampingStep; + } + prach_resources->RA_SCALING_FACTOR_BI = 1; + // Takes the value of 2-Step RA variable + if (nr_ra_ConfigGenericTwoStepRA_r16.preambleTransMax_r16) { + ra->preambleTransMax = (int)*nr_ra_ConfigGenericTwoStepRA_r16.preambleTransMax_r16; + } else { + // If 2-Step variable does not exist, it takes the value of 4-Step RA variable + ra->preambleTransMax = (int)nr_rach_ConfigCommon->rach_ConfigGeneric.preambleTransMax; + } } } @@ -637,7 +655,7 @@ static uint8_t *fill_msg3_crnti_pdu(RA_config_t *ra, uint8_t *pdu, uint16_t crnt static uint8_t *fill_msg3_pdu_from_rlc(NR_UE_MAC_INST_t *mac, uint8_t *pdu, int TBS_max) { RA_config_t *ra = &mac->ra; - // regular MSG3 with PDU coming from higher layers + // regular Msg3/MsgA_PUSCH with PDU coming from higher layers *(NR_MAC_SUBHEADER_FIXED *)pdu = (NR_MAC_SUBHEADER_FIXED){.LCID = UL_SCH_LCID_CCCH}; pdu += sizeof(NR_MAC_SUBHEADER_FIXED); tbs_size_t len = mac_rlc_data_req(mac->ue_id, @@ -651,7 +669,7 @@ static uint8_t *fill_msg3_pdu_from_rlc(NR_UE_MAC_INST_t *mac, uint8_t *pdu, int (char *)pdu, 0, 0); - AssertFatal(len > 0, "no data for Msg.3\n"); + AssertFatal(len > 0, "no data for Msg3/MsgA_PUSCH\n"); // UE Contention Resolution Identity // Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to determine whether or not the // Random Access Procedure has been successful after reception of Msg4 @@ -661,7 +679,7 @@ static uint8_t *fill_msg3_pdu_from_rlc(NR_UE_MAC_INST_t *mac, uint8_t *pdu, int return pdu; } -void nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max) +void nr_get_Msg3_MsgA_PUSCH_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max) { RA_config_t *ra = &mac->ra; @@ -674,10 +692,10 @@ void nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max) uint8_t *pdu = buf; if (ra->msg3_C_RNTI) pdu = fill_msg3_crnti_pdu(ra, pdu, mac->crnti); - else + else pdu = fill_msg3_pdu_from_rlc(mac, pdu, TBS_max); - AssertFatal(TBS_max >= pdu - buf, "Allocated resources are not enough for Msg3!\n"); + AssertFatal(TBS_max >= pdu - buf, "Allocated resources are not enough for Msg3/MsgA_PUSCH!\n"); // Padding: fill remainder with 0 LOG_D(NR_MAC, "Remaining %ld bytes, filling with padding\n", pdu - buf); while (pdu < buf + TBS_max - sizeof(NR_MAC_SUBHEADER_FIXED)) { @@ -709,13 +727,24 @@ void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB // Delay init RA procedure to allow the convergence of the IIR filter on PRACH noise measurements at gNB side if (ra->ra_state == nrRA_UE_IDLE) { - if ((mac->first_sync_frame > -1 || get_softmodem_params()->do_ra || get_softmodem_params()->nsa) && - ((MAX_FRAME_NUMBER + frame - mac->first_sync_frame) % MAX_FRAME_NUMBER) > 150) { - ra->ra_state = nrRA_GENERATE_PREAMBLE; - } else { - LOG_D(NR_MAC,"PRACH Condition not met: ra state %d, frame %d, sync_frame %d\n", ra->ra_state, frame, mac->first_sync_frame); - return; - } + LOG_D(NR_MAC, + "ra->ra_state %d frame %d mac->first_sync_frame %d xxx %d", + ra->ra_state, + frame, + mac->first_sync_frame, + ((MAX_FRAME_NUMBER + frame - mac->first_sync_frame) % MAX_FRAME_NUMBER) > 10); + if ((mac->first_sync_frame > -1 || get_softmodem_params()->do_ra || get_softmodem_params()->nsa) + && ((MAX_FRAME_NUMBER + frame - mac->first_sync_frame) % MAX_FRAME_NUMBER) > 150) { + ra->ra_state = nrRA_GENERATE_PREAMBLE; + LOG_D(NR_MAC, "PRACH Condition met: ra state %d, frame %d, sync_frame %d\n", ra->ra_state, frame, mac->first_sync_frame); + } else { + LOG_D(NR_MAC, + "PRACH Condition not met: ra state %d, frame %d, sync_frame %d\n", + ra->ra_state, + frame, + mac->first_sync_frame); + return; + } } LOG_D(NR_MAC, "[UE %d][%d.%d]: ra_state %d, RA_active %d\n", mac->ue_id, frame, nr_slot_tx, ra->ra_state, ra->RA_active); @@ -776,8 +805,7 @@ void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB nr_ra_succeeded(mac, gNB_id, frame, nr_slot_tx); } - } else if (ra->RA_window_cnt == 0 && !ra->RA_RAPID_found) { - + } else if (ra->RA_window_cnt == 0 && !ra->RA_RAPID_found && ra->ra_state != nrRA_WAIT_MSGB) { LOG_W(MAC, "[UE %d][%d:%d] RAR reception failed \n", mac->ue_id, frame, nr_slot_tx); nr_ra_failed(mac, CC_id, prach_resources, frame, nr_slot_tx); @@ -809,49 +837,102 @@ void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB } } +int16_t nr_get_RA_window_2Step(const NR_MsgA_ConfigCommon_r16_t *msgA_ConfigCommon_r16) +{ + int16_t ra_ResponseWindow = *msgA_ConfigCommon_r16->rach_ConfigCommonTwoStepRA_r16 + .rach_ConfigGenericTwoStepRA_r16.msgB_ResponseWindow_r16; + + switch (ra_ResponseWindow) { + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl1: + return 1; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl2: + return 2; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl4: + return 4; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl8: + return 8; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl10: + return 10; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl20: + return 20; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl40: + return 40; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl80: + return 80; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl160: + return 160; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl320: + return 360; + break; + default: + AssertFatal(false, "illegal msgB_responseWindow value %d\n", ra_ResponseWindow); + break; + } + return 0; +} + +int16_t nr_get_RA_window_4Step(const NR_RACH_ConfigCommon_t *rach_ConfigCommon) +{ + int16_t ra_ResponseWindow = rach_ConfigCommon->rach_ConfigGeneric.ra_ResponseWindow; + + switch (ra_ResponseWindow) { + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1: + return 1; + break; + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2: + return 2; + break; + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4: + return 4; + break; + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8: + return 8; + break; + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10: + return 10; + break; + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20: + return 20; + break; + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40: + return 40; + break; + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80: + return 80; + break; + default: + AssertFatal(false, "illegal ra_ResponseWindow value %d\n", ra_ResponseWindow); + break; + } + return 0; +} + void nr_get_RA_window(NR_UE_MAC_INST_t *mac) { RA_config_t *ra = &mac->ra; + NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon; AssertFatal(&setup->rach_ConfigGeneric != NULL, "In %s: FATAL! rach_ConfigGeneric is NULL...\n", __FUNCTION__); - NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; const double ta_Common_ms = get_ta_Common_ms(mac->sc_info.ntn_Config_r17); const int mu = mac->current_DL_BWP->scs; const int slots_per_ms = nr_slots_per_frame[mu] / 10; - + const int ra_Offset_slots = ra->RA_offset * nr_slots_per_frame[mu]; const int ta_Common_slots = (int)ceil(ta_Common_ms * slots_per_ms); ra->RA_window_cnt = ra_Offset_slots + ta_Common_slots; // taking into account the 2 frames gap introduced by OAI gNB - int ra_ResponseWindow = rach_ConfigGeneric->ra_ResponseWindow; - - switch (ra_ResponseWindow) { - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1: - ra->RA_window_cnt += 1; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2: - ra->RA_window_cnt += 2; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4: - ra->RA_window_cnt += 4; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8: - ra->RA_window_cnt += 8; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10: - ra->RA_window_cnt += 10; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20: - ra->RA_window_cnt += 20; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40: - ra->RA_window_cnt += 40; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80: - ra->RA_window_cnt += 80; - break; - } + ra->RA_window_cnt += ra->ra_type == RA_2_STEP ? nr_get_RA_window_2Step(mac->current_UL_BWP->msgA_ConfigCommon_r16) + : nr_get_RA_window_4Step(mac->current_UL_BWP->rach_ConfigCommon); } //////////////////////////////////////////////////////////////////////////// @@ -869,7 +950,7 @@ void nr_ue_contention_resolution(NR_UE_MAC_INST_t *mac, int cc_id, frame_t frame ra->t_crnti = 0; nr_timer_stop(&ra->contention_resolution_timer); // Signal PHY to quit RA procedure - LOG_E(MAC, "[UE %d] CB-RA: Contention resolution timer has expired, RA procedure has failed...\n", mac->ue_id); + LOG_E(MAC, "[UE %d] 4-Step CBRA: Contention resolution timer has expired, RA procedure has failed...\n", mac->ue_id); nr_ra_failed(mac, cc_id, prach_resources, frame, slot); } } @@ -883,14 +964,27 @@ void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame RA_config_t *ra = &mac->ra; if (ra->cfra) { - LOG_I(MAC, "[UE %d][%d.%d][RAPROC] RA procedure succeeded. CF-RA: RAR successfully received.\n", mac->ue_id, frame, slot); + LOG_I(MAC, "[UE %d][%d.%d][RAPROC] RA procedure succeeded. CFRA: RAR successfully received.\n", mac->ue_id, frame, slot); ra->RA_window_cnt = -1; + } else if (ra->ra_type == RA_2_STEP) { + LOG_A(MAC, + "[UE %d][%d.%d][RAPROC] 2-Step RA procedure succeeded. CBRA: Contention Resolution is successful.\n", + mac->ue_id, + frame, + slot); + mac->crnti = ra->t_crnti; + ra->t_crnti = 0; + LOG_D(MAC, "[UE %d][%d.%d] CBRA: cleared response window timer...\n", mac->ue_id, frame, slot); } else { - LOG_A(MAC, "[UE %d][%d.%d][RAPROC] RA procedure succeeded. CB-RA: Contention Resolution is successful.\n", mac->ue_id, frame, slot); + LOG_A(MAC, + "[UE %d][%d.%d][RAPROC] 4-Step RA procedure succeeded. CBRA: Contention Resolution is successful.\n", + mac->ue_id, + frame, + slot); nr_timer_stop(&ra->contention_resolution_timer); mac->crnti = ra->t_crnti; ra->t_crnti = 0; - LOG_D(MAC, "[UE %d][%d.%d] CB-RA: cleared contention resolution timer...\n", mac->ue_id, frame, slot); + LOG_D(MAC, "[UE %d][%d.%d] CBRA: cleared contention resolution timer...\n", mac->ue_id, frame, slot); } LOG_D(MAC, "[UE %d] clearing RA_active flag...\n", mac->ue_id); @@ -945,7 +1039,6 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(mac, prach_resources, CC_id); } else { - // Resetting RA window nr_get_RA_window(mac); } } @@ -958,7 +1051,7 @@ void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac) mac->ra.msg3_C_RNTI = true; } -void prepare_msg4_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack) +void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack) { NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[pid]; int sched_slot = current_harq->ul_slot; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index a076829a8a..b07e90e614 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -574,7 +574,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *dci, csi_payload_t *csi_report, RAR_grant_t *rar_grant, - uint16_t rnti, + rnti_t rnti, int ss_type, const nr_dci_format_t dci_format) { @@ -584,6 +584,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, int rnti_type = get_rnti_type(mac, rnti); NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP; NR_UE_ServingCell_Info_t *sc_info = &mac->sc_info; + int scs = current_UL_BWP->scs; // Common configuration pusch_config_pdu->dmrs_config_type = pusch_dmrs_type1; @@ -596,8 +597,69 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, int dmrslength = 1; NR_PUSCH_Config_t *pusch_Config = current_UL_BWP->pusch_Config; - if (rar_grant) { + AssertFatal(!((mac->ra.ra_state < nrRA_SUCCEEDED && mac->ra.ra_type == RA_2_STEP) && rar_grant), "logic error: Is not possible to have both msgA_pusch_resource and rar_grant\n"); + if (mac->ra.ra_state < nrRA_SUCCEEDED && mac->ra.ra_type == RA_2_STEP) { + NR_MsgA_PUSCH_Resource_r16_t *msgA_PUSCH_Resource = + current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16; + int S = 0; + int L = 0; + SLIV2SL(*msgA_PUSCH_Resource->startSymbolAndLengthMsgA_PO_r16, &S, &L); + tda_info->k2 = msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16; + tda_info->startSymbolIndex = S; + tda_info->nrOfSymbols = L; + l_prime_mask = get_l_prime(tda_info->nrOfSymbols, + tda_info->mapping_type, + add_pos, + dmrslength, + tda_info->startSymbolIndex, + mac->dmrs_TypeA_Position); + LOG_I(NR_MAC, + "MSGA PUSCH start_sym:%d NR Symb:%d mappingtype:%d, DMRS_MASK:%x\n", + pusch_config_pdu->start_symbol_index, + pusch_config_pdu->nr_of_symbols, + tda_info->mapping_type, + l_prime_mask); + + LOG_D(NR_MAC, + "sc_info->initial_ul_BWPStart = %d sc_info->initial_ul_BWPSize = %d\n", + sc_info->initial_ul_BWPStart, + sc_info->initial_ul_BWPSize); + pusch_config_pdu->handle = 0; + pusch_config_pdu->rb_size = msgA_PUSCH_Resource->nrofPRBs_PerMsgA_PO_r16; + pusch_config_pdu->mcs_table = 0; + pusch_config_pdu->frequency_hopping = msgA_PUSCH_Resource->msgA_IntraSlotFrequencyHopping_r16 ? *msgA_PUSCH_Resource->msgA_IntraSlotFrequencyHopping_r16 : 0; + pusch_config_pdu->dmrs_ports = 1; // is in SIB1 nrofDMRS_Sequences_r16? + pusch_config_pdu->pusch_data.new_data_indicator = 1; // new data + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; + pusch_config_pdu->ul_dmrs_symb_pos = get_l_prime(3, 0, pusch_dmrs_pos2, pusch_len1, 10, mac->dmrs_TypeA_Position); + pusch_config_pdu->transform_precoding = + *mac->current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_TransformPrecoder_r16; + pusch_config_pdu->rb_bitmap[0] = 0; + pusch_config_pdu->rb_start = msgA_PUSCH_Resource->frequencyStartMsgA_PUSCH_r16; // rb_start depends on the RO + pusch_config_pdu->bwp_size = sc_info->initial_ul_BWPSize; + pusch_config_pdu->bwp_start = sc_info->initial_ul_BWPStart; + pusch_config_pdu->subcarrier_spacing = scs; + pusch_config_pdu->cyclic_prefix = 0; + pusch_config_pdu->uplink_frequency_shift_7p5khz = 0; + pusch_config_pdu->vrb_to_prb_mapping = 0; + pusch_config_pdu->dmrs_config_type = 0; + pusch_config_pdu->data_scrambling_id = mac->physCellId; + pusch_config_pdu->ul_dmrs_scrambling_id = mac->physCellId; + pusch_config_pdu->scid = 0; + pusch_config_pdu->resource_alloc = 1; + pusch_config_pdu->tx_direct_current_location = 0; + pusch_config_pdu->mcs_index = msgA_PUSCH_Resource->msgA_MCS_r16; + pusch_config_pdu->qam_mod_order = nr_get_Qm_dl(pusch_config_pdu->mcs_index, 0); + pusch_config_pdu->start_symbol_index = S; + pusch_config_pdu->nr_of_symbols = L; + pusch_config_pdu->pusch_data.rv_index = 0; // 8.3 in 38.213 + pusch_config_pdu->pusch_data.harq_process_id = 0; + pusch_config_pdu->pusch_data.num_cb = 0; + pusch_config_pdu->tbslbrm = 0; + pusch_config_pdu->target_code_rate = nr_get_code_rate_ul(pusch_config_pdu->mcs_index, 0); + + } else if (rar_grant) { // Note: for Msg3 or MsgA PUSCH transmission the N_PRB_oh is always set to 0 int ibwp_start = sc_info->initial_ul_BWPStart; int ibwp_size = sc_info->initial_ul_BWPSize; @@ -1501,8 +1563,8 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) TBS_bytes, ra->ra_state); ulcfg_pdu->pusch_config_pdu.tx_request_body.fapiTxPdu = NULL; - if (ra->ra_state == nrRA_WAIT_RAR && !ra->cfra) { - nr_get_msg3_payload(mac, ulsch_input_buffer, TBS_bytes); + if ((ra->ra_state == nrRA_WAIT_RAR || ra->ra_state == nrRA_WAIT_MSGB) && !ra->cfra) { + nr_get_Msg3_MsgA_PUSCH_payload(mac, ulsch_input_buffer, TBS_bytes); for (int k = 0; k < TBS_bytes; k++) { LOG_D(NR_MAC, "(%i): 0x%x\n", k, ulsch_input_buffer[k]); } @@ -1553,6 +1615,9 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) LOG_A(NR_MAC, "[RAPROC][%d.%d] RA-Msg3 transmitted\n", frame_tx, slot_tx); nr_Msg3_transmitted(mac, cc_id, frame_tx, slot_tx, gNB_index); } + if (ra->ra_state == nrRA_WAIT_MSGB && !ra->cfra) { + LOG_A(NR_MAC, "[RAPROC][%d.%d] RA-MsgA-PUSCH transmitted\n", frame_tx, slot_tx); + } } ulcfg_pdu++; } @@ -2867,7 +2932,57 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, sub_fra if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) mac->if_module->scheduled_response(&scheduled_response); - nr_Msg1_transmitted(mac); + if (ra->ra_type == RA_4_STEP) { + nr_Msg1_transmitted(mac); + } else if (ra->ra_type == RA_2_STEP) { + const NR_MsgA_ConfigCommon_r16_t *msgacc = mac->current_UL_BWP->msgA_ConfigCommon_r16; + int mu = (int)*msgacc->rach_ConfigCommonTwoStepRA_r16.msgA_SubcarrierSpacing_r16; + + NR_MsgA_PUSCH_Resource_r16_t *msgA_PUSCH_Resource = + mac->current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16; + + const int n_slots_frame = nr_slots_per_frame[mu]; + slot_t msgA_pusch_slot = (slotP + msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16) % n_slots_frame; + frame_t msgA_pusch_frame = + (frameP + ((slotP + msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16) / n_slots_frame)) % 1024; + + fapi_nr_ul_config_request_pdu_t *pdu = + lockGet_ul_config(mac, msgA_pusch_frame, msgA_pusch_slot, FAPI_NR_UL_CONFIG_TYPE_PUSCH); + if (!pdu) + return; + + // Config Msg3/MsgA-PUSCH PDU + NR_tda_info_t tda_info = {0}; + AssertFatal(msgA_PUSCH_Resource->startSymbolAndLengthMsgA_PO_r16, + "Only SLIV based on startSymbolAndLengthMsgA_PO_r16 implemented\n"); + + int ret = nr_config_pusch_pdu(mac, + &tda_info, + &pdu->pusch_config_pdu, + NULL, + NULL, + NULL, + mac->ra.ra_rnti, + NR_SearchSpace__searchSpaceType_PR_common, + NR_DCI_NONE); + + if (ret != 0) + remove_ul_config_last_item(pdu); + release_ul_config(pdu, false); + + // Compute MsgB RNTI + ra->MsgB_rnti = + nr_get_MsgB_rnti(prach_occasion_info_p->start_symbol, prach_occasion_info_p->slot, prach_occasion_info_p->fdm, 0); + LOG_D(NR_MAC, "ra->ra_state %s\n", nrra_ue_text[ra->ra_state]); + ra->ra_state = nrRA_WAIT_MSGB; + ra->t_crnti = 0; + mac->crnti = 0; + ra->ra_rnti = 0; + } else { + AssertFatal(false, "RA type %d not implemented!\n", ra->ra_type); + } + + // rnti = ra->t_crnti; } // is_nr_prach_slot } // if is_nr_UL_slot } diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 2da11f109c..c4faefa0fa 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1127,7 +1127,7 @@ void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, uint8_t ack_nac LOG_D(PHY,"Updating harq_status for harq_id %d, ack/nak %d\n", harq_pid, current_harq->ack); // we can prepare feedback for MSG4 in advance if (mac->ra.ra_state == nrRA_WAIT_CONTENTION_RESOLUTION) - prepare_msg4_feedback(mac, harq_pid, ack_nack); + prepare_msg4_msgb_feedback(mac, harq_pid, ack_nack); else { current_harq->ack = ack_nack; current_harq->ack_received = true; From 19e0df13a96c02158a8d26185ea2a6877e30cf50 Mon Sep 17 00:00:00 2001 From: ndomingues Date: Tue, 14 May 2024 11:32:12 +0100 Subject: [PATCH 10/15] Add support for Random Access MsgB RNTI --- common/utils/nr/nr_common.h | 1 + openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 1 + .../LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c | 15 ++++++++++++++- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 3 +++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 9087f335c5..5f4c58d386 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -53,6 +53,7 @@ R(TYPE_P_RNTI_) /* Paging RNTI */ \ R(TYPE_SI_RNTI_) /* System information RNTI */ \ R(TYPE_RA_RNTI_) /* Random Access RNTI */ \ + R(TYPE_MSGB_RNTI_) /* Random Access MsgB RNTI */ \ R(TYPE_SP_CSI_RNTI_) /* Semipersistent CSI reporting on PUSCH */ \ R(TYPE_SFI_RNTI_) /* Slot Format Indication on the given cell */ \ R(TYPE_INT_RNTI_) /* Indication pre-emption in DL */ \ diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index cbdcb51d22..835df85c04 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -655,6 +655,7 @@ NR_tda_info_t get_dl_tda_info(const NR_UE_DL_BWP_t *dl_BWP, case TYPE_CS_RNTI_: case TYPE_MCS_C_RNTI_: case TYPE_RA_RNTI_: + case TYPE_MSGB_RNTI_: case TYPE_TC_RNTI_: if(tdalist) tda_info = set_tda_info_from_list(tdalist, tda_index); 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 550ae2b8da..1c01f84d4d 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -266,6 +266,14 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, rel15->rnti = mac->ra.ra_rnti; rel15->SubcarrierSpacing = current_DL_BWP->scs; break; + case TYPE_MSGB_RNTI_: + // we use the initial DL BWP + sps = current_DL_BWP->cyclicprefix == NULL ? 14 : 12; + monitoringSymbolsWithinSlot = + (ss->monitoringSymbolsWithinSlot->buf[0] << (sps - 8)) | (ss->monitoringSymbolsWithinSlot->buf[1] >> (16 - sps)); + rel15->rnti = mac->ra.MsgB_rnti; + rel15->SubcarrierSpacing = current_DL_BWP->scs; + break; case TYPE_P_RNTI_: break; case TYPE_CS_RNTI_: @@ -571,7 +579,12 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl if (mac->state == UE_PERFORMING_RA && mac->ra.ra_state >= nrRA_WAIT_RAR) { // if RA is ongoing use RA search space if (is_ss_monitor_occasion(frame, slot, slots_per_frame, pdcch_config->ra_SS)) { - int rnti_type = mac->ra.ra_state == nrRA_WAIT_RAR ? TYPE_RA_RNTI_ : TYPE_TC_RNTI_; + nr_rnti_type_t rnti_type = 0; + if (mac->ra.ra_type == RA_4_STEP) { + rnti_type = mac->ra.ra_state == nrRA_WAIT_RAR ? TYPE_RA_RNTI_ : TYPE_TC_RNTI_; + } else { + rnti_type = TYPE_MSGB_RNTI_; + } config_dci_pdu(mac, dl_config, rnti_type, slot, pdcch_config->ra_SS); } } else if (mac->state == UE_CONNECTED) { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 7844b31132..cdec17bce6 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -161,6 +161,8 @@ int get_rnti_type(const NR_UE_MAC_INST_t *mac, const uint16_t rnti) if (rnti == ra->ra_rnti) { rnti_type = TYPE_RA_RNTI_; + } else if (rnti == ra->MsgB_rnti && (ra->ra_state == nrRA_WAIT_MSGB || ra->ra_state == nrRA_WAIT_CONTENTION_RESOLUTION)) { + rnti_type = TYPE_MSGB_RNTI_; } else if (rnti == ra->t_crnti && (ra->ra_state == nrRA_WAIT_RAR || ra->ra_state == nrRA_WAIT_CONTENTION_RESOLUTION)) { rnti_type = TYPE_TC_RNTI_; } else if (rnti == mac->crnti) { @@ -3347,6 +3349,7 @@ static nr_dci_format_t nr_extract_dci_00_10(NR_UE_MAC_INST_t *mac, dci_pdu_rel15->format_indicator = format_indicator; break; case TYPE_TC_RNTI_ : + case TYPE_MSGB_RNTI_: // Identifier for DCI formats EXTRACT_DCI_ITEM(format_indicator, 1); if (format_indicator == 1) { From 9d786bdee74e8011f44c3b1e716d25028b42abc9 Mon Sep 17 00:00:00 2001 From: ndomingues Date: Tue, 14 May 2024 11:33:44 +0100 Subject: [PATCH 11/15] Implementation of RA 2-Step MsgB procedures at gNB --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 161 ++++++++++++++---- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 2 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 5 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 4 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 13 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 4 +- 6 files changed, 140 insertions(+), 49 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 3ffeb22228..8e91e0424f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -553,6 +553,76 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP } } +int nr_fill_successrar(const NR_UE_sched_ctrl_t *ue_sched_ctl, + rnti_t crnti, + const unsigned char *ue_cont_res_id, + uint8_t resource_indicator, + uint8_t timing_indicator, + unsigned char *mac_pdu, + int mac_pdu_length) +{ + LOG_D(NR_MAC, "mac_pdu_length = %d\n", mac_pdu_length); + int timing_advance_cmd = ue_sched_ctl->ta_update; + // TS 38.321 - Figure 6.1.5a-1: BI MAC subheader + NR_RA_HEADER_BI_MSGB *bi = (NR_RA_HEADER_BI_MSGB *)&mac_pdu[mac_pdu_length]; + mac_pdu_length += sizeof(NR_RA_HEADER_BI_MSGB); + + bi->E = 1; + bi->T1 = 0; + bi->T2 = 0; + bi->R = 0; + bi->BI = 0; // BI = 0, 5ms + + // TS 38.321 - Figure 6.1.5a-3: SuccessRAR MAC subheader + NR_RA_HEADER_SUCCESS_RAR_MSGB *SUCESS_RAR_header = (NR_RA_HEADER_SUCCESS_RAR_MSGB *)&mac_pdu[mac_pdu_length]; + mac_pdu_length += sizeof(NR_RA_HEADER_SUCCESS_RAR_MSGB); + + SUCESS_RAR_header->E = 0; + SUCESS_RAR_header->T1 = 0; + SUCESS_RAR_header->T2 = 1; + SUCESS_RAR_header->S = 0; + SUCESS_RAR_header->R = 0; + + // TS 38.321 - Figure 6.2.3a-2: successRAR + NR_MAC_SUCCESS_RAR *successRAR = (NR_MAC_SUCCESS_RAR *)&mac_pdu[mac_pdu_length]; + mac_pdu_length += sizeof(NR_MAC_SUCCESS_RAR); + + successRAR->CONT_RES_1 = ue_cont_res_id[0]; + successRAR->CONT_RES_2 = ue_cont_res_id[1]; + successRAR->CONT_RES_3 = ue_cont_res_id[2]; + successRAR->CONT_RES_4 = ue_cont_res_id[3]; + successRAR->CONT_RES_5 = ue_cont_res_id[4]; + successRAR->CONT_RES_6 = ue_cont_res_id[5]; + successRAR->R = 0; + successRAR->CH_ACESS_CPEXT = 1; + successRAR->TPC = ue_sched_ctl->tpc0; + successRAR->HARQ_FTI = timing_indicator; + successRAR->PUCCH_RI = resource_indicator; + successRAR->TA1 = (uint8_t)(timing_advance_cmd >> 8); // 4 MSBs of timing advance; + successRAR->TA2 = (uint8_t)(timing_advance_cmd & 0xff); // 8 LSBs of timing advance; + successRAR->CRNTI_1 = (uint8_t)(crnti >> 8); // 8 MSBs of rnti + successRAR->CRNTI_2 = (uint8_t)(crnti & 0xff); // 8 LSBs of rnti + + LOG_D(NR_MAC, + "successRAR: Contention Resolution ID 0x%02x%02x%02x%02x%02x%02x R 0x%01x CH_ACESS_CPEXT 0x%02x TPC 0x%02x HARQ_FTI 0x%03x " + "PUCCH_RI 0x%04x TA 0x%012x CRNTI 0x%04x\n", + successRAR->CONT_RES_1, + successRAR->CONT_RES_2, + successRAR->CONT_RES_3, + successRAR->CONT_RES_4, + successRAR->CONT_RES_5, + successRAR->CONT_RES_6, + successRAR->R, + successRAR->CH_ACESS_CPEXT, + successRAR->TPC, + successRAR->HARQ_FTI, + successRAR->PUCCH_RI, + timing_advance_cmd, + crnti); + LOG_D(NR_MAC, "mac_pdu_length = %d\n", mac_pdu_length); + return mac_pdu_length; +} + static bool ra_contains_preamble(const NR_RA_t *ra, uint16_t preamble_index) { for (int j = 0; j < ra->preambles.num_preambles; j++) { @@ -1854,33 +1924,32 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, LOG_D(NR_MAC, "numDlDci: %i\n", pdcch_pdu_rel15->numDlDci); } -static 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) +static void nr_generate_Msg4_MsgB(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; - // if it is a DL slot, if the RA is in MSG4 state + // if it is a DL slot, if the RA is in MSG4 state if (is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slotP / 64], slotP)) { + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + NR_SearchSpace_t *ss = ra->ra_ss; + const char *ra_type_str = ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4"; + NR_ControlResourceSet_t *coreset = ra->coreset; + AssertFatal(coreset != NULL, "Coreset cannot be null for RA %s\n", ra_type_str); - NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - NR_SearchSpace_t *ss = ra->ra_ss; + uint16_t mac_sdu_length = 0; - NR_ControlResourceSet_t *coreset = ra->coreset; - AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg4\n"); - - uint16_t mac_sdu_length = 0; - - NR_UE_info_t *UE = find_nr_UE(&nr_mac->UE_info, ra->rnti); - if (!UE) { - LOG_E(NR_MAC, "want to generate Msg4, but rnti %04x not in the table\n", ra->rnti); - return; + NR_UE_info_t *UE = find_nr_UE(&nr_mac->UE_info, ra->rnti); + if (!UE) { + LOG_E(NR_MAC, "want to generate %s, but rnti %04x not in the table\n", ra_type_str, ra->rnti); + return; } NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; @@ -1975,7 +2044,8 @@ static void nr_generate_Msg4(module_id_t module_idP, } else { uint8_t subheader_len = (mac_sdu_length < 256) ? sizeof(NR_MAC_SUBHEADER_SHORT) : sizeof(NR_MAC_SUBHEADER_LONG); - pdu_length = mac_sdu_length + subheader_len + 7; //7 is contetion resolution length + pdu_length = mac_sdu_length + subheader_len + 13; // 13 is contention resolution length of msgB. It is divided into 3 parts: + // BI MAC subheader (1 Oct) + SuccessRAR MAC subheader (1 Oct) + SuccessRAR (11 Oct) } // increase PRBs until we get to BWPSize or TBS is bigger than MAC PDU size @@ -1990,7 +2060,7 @@ static void nr_generate_Msg4(module_id_t module_idP, rbSize, msg4_tda.nrOfSymbols, dmrs_info.N_PRB_DMRS * dmrs_info.N_DMRS_SLOT, 0, tb_scaling,1) >> 3; } while (tb_size < pdu_length && mcsIndex<=28); - AssertFatal(tb_size >= pdu_length,"Cannot allocate Msg4\n"); + AssertFatal(tb_size >= pdu_length, "Cannot allocate %s\n", ra_type_str); int i = 0; uint16_t *vrb_map = cc[CC_id].vrb_map[beam.idx]; @@ -2053,9 +2123,22 @@ static void nr_generate_Msg4(module_id_t module_idP, uint8_t *buf = (uint8_t *) harq->transportBlock; // Bytes to be transmitted if (harq->round == 0) { - // UE Contention Resolution Identity MAC CE - uint16_t mac_pdu_length = nr_write_ce_dlsch_pdu(module_idP, nr_mac->sched_ctrlCommon, buf, 255, ra->cont_res_id); - LOG_D(NR_MAC,"Encoded contention resolution mac_pdu_length %d\n",mac_pdu_length); + uint16_t mac_pdu_length = 0; + if (ra->ra_type == RA_4_STEP) { + // UE Contention Resolution Identity MAC CE + mac_pdu_length = nr_write_ce_dlsch_pdu(module_idP, nr_mac->sched_ctrlCommon, buf, 255, ra->cont_res_id); + } else if (ra->ra_type == RA_2_STEP) { + mac_pdu_length = nr_fill_successrar(nr_mac->sched_ctrlCommon, + ra->rnti, + ra->cont_res_id, + pucch->resource_indicator, + pucch->timing_indicator, + buf, + mac_pdu_length); + } else { + AssertFatal(false, "RA type %d not implemented!\n", ra->ra_type); + } + uint8_t buffer[CCCH_SDU_SIZE]; uint8_t mac_subheader_len = sizeof(NR_MAC_SUBHEADER_SHORT); // Get RLC data on the SRB (RRCSetup, RRCReestablishment) @@ -2140,7 +2223,7 @@ static void nr_generate_Msg4(module_id_t module_idP, if (pucch == NULL) { LOG_A(NR_MAC, "(UE RNTI 0x%04x) Skipping Ack of RA-Msg4. CBRA procedure succeeded!\n", ra->rnti); - UE->Msg4_ACKed = true; + UE->Msg4_MsgB_ACKed = true; // Pause scheduling according to: // 3GPP TS 38.331 Section 12 Table 12.1-1: UE performance requirements for RRC procedures for UEs @@ -2151,17 +2234,18 @@ static void nr_generate_Msg4(module_id_t module_idP, nr_clear_ra_proc(ra); } else { - ra->ra_state = nrRA_WAIT_Msg4_ACK; + ra->ra_state = nrRA_WAIT_Msg4_MsgB_ACK; LOG_I(NR_MAC,"UE %04x Generate msg4: feedback at %4d.%2d, payload %d bytes, next state WAIT_Msg4_ACK\n", ra->rnti, pucch->frame, pucch->ul_slot, harq->tb_size); } } } -static void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra) +static void nr_check_Msg4_MsgB_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra) { + const char *ra_type_str = ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4"; NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, ra->rnti); if (!UE) { - LOG_E(NR_MAC, "Cannot check Msg4 ACK/NACK, rnti %04x not in the table\n", ra->rnti); + LOG_E(NR_MAC, "Cannot check %s ACK/NACK, rnti %04x not in the table\n", ra_type_str, ra->rnti); return; } const int current_harq_pid = ra->harq_pid; @@ -2173,10 +2257,14 @@ static void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, s if (harq->is_waiting == 0) { if (harq->round == 0) { - if (UE->Msg4_ACKed) { - LOG_A(NR_MAC, "(UE RNTI 0x%04x) Received Ack of RA-Msg4. CBRA procedure succeeded!\n", ra->rnti); + if (UE->Msg4_MsgB_ACKed) { + LOG_A(NR_MAC, + "%4d.%2d UE %04x: Received Ack of %s. CBRA procedure succeeded!\n", + frame, slot, ra->rnti, ra_type_str); } else { - LOG_I(NR_MAC, "%4d.%2d UE %04x: RA Procedure failed at Msg4!\n", frame, slot, ra->rnti); + LOG_I(NR_MAC, + "%4d.%2d UE %04x: RA Procedure failed at %s!\n", + frame, slot, ra->rnti, ra_type_str); nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs); } @@ -2192,8 +2280,8 @@ static void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, s remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); } } else { - LOG_I(NR_MAC, "(UE %04x) Received Nack of RA-Msg4. Preparing retransmission!\n", ra->rnti); - ra->ra_state = nrRA_Msg4; + LOG_I(NR_MAC, "(UE %04x) Received Nack in %s, preparing retransmission!\n", ra->rnti, nrra_text[ra->ra_state]); + ra->ra_state = ra->ra_type == RA_4_STEP ? nrRA_Msg4 : nrRA_MsgB; } } } @@ -2365,10 +2453,11 @@ void nr_schedule_RA(module_id_t module_idP, nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra, ul_dci_req); break; case nrRA_Msg4: - nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); + case nrRA_MsgB: + nr_generate_Msg4_MsgB(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); break; - case nrRA_WAIT_Msg4_ACK: - nr_check_Msg4_Ack(module_idP, CC_id, frameP, slotP, ra); + case nrRA_WAIT_Msg4_MsgB_ACK: + nr_check_Msg4_MsgB_Ack(module_idP, CC_id, frameP, slotP, ra); break; default: break; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 1307df70ac..e1432340c4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -627,7 +627,7 @@ static void pf_dl(module_id_t module_id, /* Loop UE_info->list to check retransmission */ UE_iterator(UE_list, UE) { - if (UE->Msg4_ACKed != true) + if (!UE->Msg4_MsgB_ACKed) continue; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 4cf6da7433..b68eaac512 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2476,10 +2476,7 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf UE->uid = uid_linear_allocator_new(&UE_info->uid_allocator); UE->CellGroup = CellGroup; - if (CellGroup) - UE->Msg4_ACKed = true; - else - UE->Msg4_ACKed = false; + UE->Msg4_MsgB_ACKed = CellGroup != NULL; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; memset(sched_ctrl, 0, sizeof(*sched_ctrl)); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index bf33bfbac6..189f74a0ab 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -1041,8 +1041,8 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, remove_front_nr_list(&sched_ctrl->feedback_dl_harq); LOG_D(NR_MAC,"%4d.%2d bit %d pid %d ack/nack %d\n",frame, slot, harq_bit,pid,harq_value); handle_dl_harq(UE, pid, harq_value == 0 && harq_confidence == 0, nrmac->dl_bler.harq_round_max); - if (!UE->Msg4_ACKed && harq_value == 0 && harq_confidence == 0) - UE->Msg4_ACKed = true; + if (!UE->Msg4_MsgB_ACKed && harq_value == 0 && harq_confidence == 0) + UE->Msg4_MsgB_ACKed = true; if (harq_confidence == 1) UE->mac_stats.pucch0_DTX++; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 234420f39d..c180548511 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -921,7 +921,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, // The UE identified by C-RNTI still exists at the gNB // Reset Msg4_ACKed to not schedule ULSCH and DLSCH before RRC Reconfiguration - UE->Msg4_ACKed = false; + UE->Msg4_MsgB_ACKed = false; nr_mac_reset_ul_failure(&UE->UE_sched_ctrl); // Reset HARQ processes reset_dl_harq_list(&UE->UE_sched_ctrl); @@ -956,8 +956,13 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, // the function is only called to decode the contention resolution sub-header nr_process_mac_pdu(gnb_mod_idP, UE, CC_idP, frameP, slotP, sduP, sdu_lenP, -1); - LOG_I(NR_MAC, "Activating scheduling RA-Msg4 for TC_RNTI 0x%04x (state %s)\n", ra->rnti, nrra_text[ra->ra_state]); - ra->ra_state = nrRA_Msg4; + LOG_I(NR_MAC, + "Activating scheduling %s for TC_RNTI 0x%04x (state %s)\n", + ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4", + ra->rnti, + nrra_text[ra->ra_state]); + ra->ra_state = ra->ra_type == RA_2_STEP ? nrRA_MsgB : nrRA_Msg4; + LOG_D(NR_MAC, "TC_RNTI 0x%04x next RA state %s\n", ra->rnti, nrra_text[ra->ra_state]); return; } } @@ -1794,7 +1799,7 @@ static void pf_ul(module_id_t module_id, UE_iterator(UE_list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - if (UE->Msg4_ACKed != true || sched_ctrl->ul_failure) + if (!UE->Msg4_MsgB_ACKed || sched_ctrl->ul_failure) continue; LOG_D(NR_MAC,"pf_ul: preparing UL scheduling for UE %04x\n",UE->rnti); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 556d30f3fd..9fc34b8243 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -121,7 +121,7 @@ typedef enum { nrRA_Msg3_retransmission, nrRA_Msg4, nrRA_MsgB, - nrRA_WAIT_Msg4_ACK, + nrRA_WAIT_Msg4_MsgB_ACK, } RA_gNB_state_t; static const char *const nrra_text[] = @@ -758,7 +758,7 @@ typedef struct { NR_UE_NR_Capability_t *capability; // UE selected beam index uint8_t UE_beam_index; - bool Msg4_ACKed; + bool Msg4_MsgB_ACKed; float ul_thr_ue; float dl_thr_ue; long pdsch_HARQ_ACK_Codebook; From acd776fe289037691548b05a0b5695acb3c90f50 Mon Sep 17 00:00:00 2001 From: ndomingues Date: Tue, 14 May 2024 11:35:34 +0100 Subject: [PATCH 12/15] Implementation of RA 2-Step MsgB procedures at UE --- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 15 ++- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 125 ++++++++++++++++--- 2 files changed, 122 insertions(+), 18 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 9006c84be2..ffa09ccb25 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -312,10 +312,17 @@ typedef struct { nr_ra_type_t ra_type; /// RA rx frame offset: compensate RA rx offset introduced by OAI gNB. uint8_t RA_offset; - /// RA-RNTI - rnti_t ra_rnti; - /// MsgB-RNTI - rnti_t MsgB_rnti; + /// MsgB SuccessRAR MAC subheader + int8_t MsgB_R; + int8_t MsgB_CH_ACESS_CPEXT; + uint8_t MsgB_TPC; + int8_t MsgB_HARQ_FTI; + uint16_t timing_advance_command; + int8_t PUCCH_RI; + /// RA-rnti + uint16_t ra_rnti; + /// MsgB RNTI + uint16_t MsgB_rnti; /// Temporary CRNTI uint16_t t_crnti; /// number of attempt for rach diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index cdec17bce6..6ba441bad1 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3437,6 +3437,101 @@ static void set_time_alignment(NR_UE_MAC_INST_t *mac, int ta, ta_type_t type, in nr_timer_start(&mac->time_alignment_timer); } +static bool check_ra_contention_resolution(const uint8_t *pdu, const uint8_t *cont_res) +{ + if (IS_SOFTMODEM_IQPLAYER) // Control is bypassed when replaying IQs (BMC) + return true; + for (int i = 0; i < 6; i++) { + if (pdu[i] != cont_res[i]) { + return false; + } + } + return true; +} + +static int nr_ue_validate_successrar(uint8_t *pduP, + int32_t pdu_len, + NR_UE_MAC_INST_t *mac, + uint8_t gNB_index, + frame_t frameP, + int slot) +{ + // TS 38.321 - Figure 6.1.5a-1: BI MAC subheader + // TS 38.321 - Figure 6.1.5a-3: SuccessRAR MAC subheader + int n = 0; + uint8_t E = 1; + uint8_t cont_res_id[6]; + RA_config_t *ra = &mac->ra; + + while (n < pdu_len && E) { + E = (pduP[n] >> 7) & 0x1; + uint8_t SUCESS_RAR_header_T1 = (pduP[n] >> 6) & 0x1; + if (SUCESS_RAR_header_T1 == 0) { // T2 exist + int SUCESS_RAR_header_T2 = (pduP[n] >> 5) & 0x1; + if (SUCESS_RAR_header_T2 == 0) { // BI + ra->RA_backoff_indicator = pduP[n] & 0x0F; + n++; + } else { // S + n++; + // TS 38.321 - Figure 6.2.3a-2: successRAR + for (int i = 0; i < 6; ++i) + cont_res_id[i] = pduP[n + i]; + n += 6; + // Oct 7 + ra->MsgB_R = 0; + ra->MsgB_CH_ACESS_CPEXT = (pduP[n] >> 5) & 0x3; + ra->MsgB_TPC = (pduP[n] >> 3) & 3; + ra->MsgB_HARQ_FTI = (int8_t)pduP[n] & 0x7; + // Oct 8 + n++; + ra->PUCCH_RI = ((int8_t)pduP[n] >> 4) & 0x0F; + // Oct 8 and Oct 9 + ra->timing_advance_command = ((uint16_t)(pduP[n] & 0xf) << 8) | pduP[n + 1]; + n += 2; + // Oct 10 and Oct 11 + ra->t_crnti = ((uint16_t)pduP[n] << 8) | pduP[n + 1]; + n += 2; + + LOG_D(NR_MAC, + "successRAR: Contention Resolution ID 0x%02x%02x%02x%02x%02x%02x R 0x%01x CH_ACESS_CPEXT 0x%02x TPC 0x%02x " + "HARQ_FTI 0x%03x PUCCH_RI 0x%04x TA 0x%012x CRNTI 0x%04x\n", + cont_res_id[0], + cont_res_id[1], + cont_res_id[2], + cont_res_id[3], + cont_res_id[4], + cont_res_id[5], + ra->MsgB_R, + ra->MsgB_CH_ACESS_CPEXT, + ra->MsgB_TPC, + ra->MsgB_HARQ_FTI, + ra->PUCCH_RI, + ra->timing_advance_command, + ra->t_crnti); + + bool ra_success = check_ra_contention_resolution(cont_res_id, ra->cont_res_id); + + if (ra->RA_active && ra_success) { + nr_ra_succeeded(mac, gNB_index, frameP, slot); + } else if (!ra_success) { + // nr_ra_failed(mac, CC_id, &ra->prach_resources, frameP, slot); + ra->ra_state = nrRA_UE_IDLE; + ra->RA_active = 0; + } + } + } else { // RAPID + int RAPID = pduP[n] & 0x3F; + n++; + LOG_D(MAC, "RAPID %d\n", RAPID); + AssertFatal(false, "FallbackRAR not implemented yet!\n"); + } + } + const int ta = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND; + + set_time_alignment(mac, ta, adjustment_ta, frameP, slot); + return n; +} + /////////////////////////////////// // brief: nr_ue_process_mac_pdu // function: parsing DL PDU header @@ -3460,9 +3555,12 @@ static void set_time_alignment(NR_UE_MAC_INST_t *mac, int ta, ta_type_t type, in // // |0|1|2|3|4|5|6|7| bit-wise // |R|R| LCID | -// LCID: The Logical Channel ID field identifies the logical channel instance of the corresponding MAC SDU or the type of the corresponding MAC CE or padding as described -// in Tables 6.2.1-1 and 6.2.1-2 for the DL-SCH and UL-SCH respectively. There is one LCID field per MAC subheader. The LCID field size is 6 bits; -// L: The Length field indicates the length of the corresponding MAC SDU or variable-sized MAC CE in bytes. There is one L field per MAC subheader except for subheaders +// LCID: The Logical Channel ID field identifies the logical channel instance of the corresponding MAC SDU or the type of the +// corresponding MAC CE or padding as described +// in Tables 6.2.1-1 and 6.2.1-2 for the DL-SCH and UL-SCH respectively. There is one LCID field per MAC subheader. The LCID +// field size is 6 bits; +// L: The Length field indicates the length of the corresponding MAC SDU or variable-sized MAC CE in bytes. There is one L field +// per MAC subheader except for subheaders // corresponding to fixed-sized MAC CEs and padding. The size of the L field is indicated by the F field; // F: lenght of L is 0:8 or 1:16 bits wide // R: Reserved bit, set to zero. @@ -3478,17 +3576,24 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i uint8_t done = 0; RA_config_t *ra = &mac->ra; - if (!pduP){ + if (!pduP) { return; } - LOG_D(MAC, "[%d.%d]: processing PDU %d (with length %d) of %d total number of PDUs...\n", + LOG_D(MAC, + "[%d.%d]: processing PDU %d (with length %d) of %d total number of PDUs...\n", frameP, slot, pdu_id, pdu_len, dl_info->rx_ind->number_pdus); + if (ra->ra_type == RA_2_STEP && ra->ra_state == nrRA_WAIT_MSGB) { + int n = nr_ue_validate_successrar(pduP, pdu_len, mac, gNB_index, frameP, slot); + pduP += n; + pdu_len -= n; + } + while (!done && pdu_len > 0){ uint16_t mac_len = 0x0000; uint16_t mac_subheader_len = 0x0001; // default to fixed-length subheader = 1-oct @@ -3621,15 +3726,7 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i pduP[5], pduP[6]); - bool ra_success = true; - if (!IS_SOFTMODEM_IQPLAYER) { // Control is bypassed when replaying IQs (BMC) - for(int i = 0; i < mac_len; i++) { - if(ra->cont_res_id[i] != pduP[i + 1]) { - ra_success = false; - break; - } - } - } + bool ra_success = check_ra_contention_resolution(&pduP[1], ra->cont_res_id); if (ra->RA_active && ra_success) { nr_ra_succeeded(mac, gNB_index, frameP, slot); From 88a9515321c0fa540c43c129ddaf53c6d3afb408 Mon Sep 17 00:00:00 2001 From: ndomingues Date: Tue, 14 May 2024 11:36:36 +0100 Subject: [PATCH 13/15] Update FEATURE_SET with 2-Step RA feature --- doc/FEATURE_SET.md | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index 5469687ade..eb1027bb3e 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -105,10 +105,18 @@ These modes of operation are supported: - MAC <-> PHY data interface using FAPI P7 interface for BCH PDU, DCI PDU, PDSCH PDU - Scheduler procedures for SIB1 - Scheduler procedures for RA - - Contention Free RA procedure - - Contention Based RA procedure - - Msg3 can transfer uplink CCCH, DTCH or DCCH messages - - CBRA can be performed using MAC CE or C-RNTI + - 4-Step RA + - Contention Free RA procedure + - Contention Based RA procedure + - Msg3 can transfer uplink CCCH, DTCH or DCCH messages + - CBRA can be performed using MAC CE for C-RNTI + - Is not possible to use 2-Step RA and 4-Step RA at the same time + - 2-Step RA + - Contention Based RA procedure + - MsgA can transfer uplink CCCH, DTCH or DCCH messages + - CBRA can be performed using MAC CE for C-RNTI + - Is not possible to use 2-Step RA and 4-Step RA at the same time + - Fallback not supported - Scheduler procedures for CSI-RS - MAC downlink scheduler - phy-test scheduler (fixed allocation and usable also without UE) @@ -310,9 +318,15 @@ These modes of operation are supported: * Random access procedure (needs improvement, there is still not a clear separation between MAC and PHY) - Mapping SSBs to multiple ROs - Scheduling of PRACH - - Processing of RAR - - Transmission and re-transmission of Msg3 - - Msg4 and contention resolution + - 4-Step RA + - Processing of RAR + - Transmission and re-transmission of Msg3 + - Msg4 and contention resolution + - 2-Step RA + - Transmission of MsgA-PUSCH + - Reception of MsgB + - Processing of SuccessRAR + - Fallback not supported * DCI processing - format 10 (RA-RNTI, C-RNTI, SI-RNTI, TC-RNTI) - format 00 (C-RNTI, TC-RNTI) From 64ee6a4776ae8c42826c7087e4a90f7f947e6763 Mon Sep 17 00:00:00 2001 From: ndomingues Date: Mon, 7 Oct 2024 16:35:16 +0100 Subject: [PATCH 14/15] Use common function to get mu at UE for PRACH --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 27 +++++++------------ openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 13 ++------- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 19 +++++++++---- 4 files changed, 26 insertions(+), 35 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 835df85c04..13b45d2e10 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -5333,28 +5333,19 @@ int get_FeedbackDisabled(NR_DownlinkHARQ_FeedbackDisabled_r17_t *downlinkHARQ_Fe return (downlinkHARQ_FeedbackDisabled_r17->buf[byte_index] >> (7 - bit_index)) & 1; } -int nr_get_mu(const NR_UplinkConfigCommon_t *uplinkConfigCommon) +int nr_get_prach_mu(const NR_MsgA_ConfigCommon_r16_t *msgacc, const NR_RACH_ConfigCommon_t *rach_ConfigCommon) { int mu; - NR_BWP_UplinkCommon_t *initialUplinkBWP = uplinkConfigCommon->initialUplinkBWP; // if 2-Step configuration file exists - if (initialUplinkBWP->ext1 && initialUplinkBWP->ext1->msgA_ConfigCommon_r16) { - if (initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->rach_ConfigCommonTwoStepRA_r16.msgA_SubcarrierSpacing_r16) { - // Choose Subcarrier Spacing of configuration file of 2-Step - const NR_MsgA_ConfigCommon_r16_t *msgacc = initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup; - mu = *msgacc->rach_ConfigCommonTwoStepRA_r16.msgA_SubcarrierSpacing_r16; - } else { - // Choose Subcarrier Spacing of configuration file of 4-Step - mu = uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - } - } else { - if (initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) { - mu = *initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing; - } else { - mu = uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - } - } + if (msgacc && msgacc->rach_ConfigCommonTwoStepRA_r16.msgA_SubcarrierSpacing_r16) { + // Choose Subcarrier Spacing of configuration file of 2-Step + mu = *msgacc->rach_ConfigCommonTwoStepRA_r16.msgA_SubcarrierSpacing_r16; + } else if (rach_ConfigCommon->msg1_SubcarrierSpacing) { + // Choose Subcarrier Spacing of configuration file of 4-Step + mu = *rach_ConfigCommon->msg1_SubcarrierSpacing; + } else + AssertFatal(false, "PRACH subcarrier spacing mandatory present for L139, not supported otherwise\n"); return mu; } diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 990e91db65..a4930aec47 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -327,6 +327,6 @@ int get_nrofHARQ_ProcessesForPDSCH(const NR_UE_ServingCell_Info_t *sc_info); int get_nrofHARQ_ProcessesForPUSCH(const NR_UE_ServingCell_Info_t *sc_info); -int nr_get_mu(const NR_UplinkConfigCommon_t *uplinkConfigCommon); +int nr_get_prach_mu(const NR_MsgA_ConfigCommon_r16_t *msgacc, const NR_RACH_ConfigCommon_t *rach_ConfigCommon); #endif diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index b07e90e614..a6ecb7fbe0 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1804,13 +1804,6 @@ static void build_ro_list(NR_UE_MAC_INST_t *mac) NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; config_index = rach_ConfigGeneric->prach_ConfigurationIndex; - - int mu; - if (setup->msg1_SubcarrierSpacing) - mu = *setup->msg1_SubcarrierSpacing; - else - mu = mac->current_UL_BWP->scs; - msg1_FDM = rach_ConfigGeneric->msg1_FDM; switch (msg1_FDM){ @@ -1830,6 +1823,7 @@ static void build_ro_list(NR_UE_MAC_INST_t *mac) int unpaired = mac->phy_config.config_req.cell_config.frame_duplex_type; const int64_t *prach_config_info_p = get_prach_config_info(mac->frequency_range, config_index, unpaired); + int mu = nr_get_prach_mu(mac->current_UL_BWP->msgA_ConfigCommon_r16, setup); // Identify the proper PRACH Configuration Index table according to the operating frequency LOG_D(NR_MAC,"mu = %u, PRACH config index = %u, unpaired = %u\n", mu, config_index, unpaired); @@ -2935,12 +2929,9 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, sub_fra if (ra->ra_type == RA_4_STEP) { nr_Msg1_transmitted(mac); } else if (ra->ra_type == RA_2_STEP) { - const NR_MsgA_ConfigCommon_r16_t *msgacc = mac->current_UL_BWP->msgA_ConfigCommon_r16; - int mu = (int)*msgacc->rach_ConfigCommonTwoStepRA_r16.msgA_SubcarrierSpacing_r16; - NR_MsgA_PUSCH_Resource_r16_t *msgA_PUSCH_Resource = mac->current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16; - + int mu = nr_get_prach_mu(mac->current_UL_BWP->msgA_ConfigCommon_r16, setup); const int n_slots_frame = nr_slots_per_frame[mu]; slot_t msgA_pusch_slot = (slotP + msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16) % n_slots_frame; frame_t msgA_pusch_frame = diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 8e91e0424f..0ce8041d6c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -96,8 +96,10 @@ static int16_t ssb_index_from_prach(module_id_t module_idP, uint8_t config_period = 1; uint16_t prach_occasion_id = -1; uint8_t num_active_ssb = cc->num_active_ssb; - - int mu = nr_get_mu(scc->uplinkConfigCommon); + NR_MsgA_ConfigCommon_r16_t *msgacc = NULL; + if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 && scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16) + msgacc = scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup; + int mu = nr_get_prach_mu(msgacc, rach_ConfigCommon); get_nr_prach_info_from_index(config_index, (int)frameP, @@ -201,7 +203,10 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac) break; } - int mu = nr_get_mu(scc->uplinkConfigCommon); + NR_MsgA_ConfigCommon_r16_t *msgacc = NULL; + if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 && scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16) + msgacc = scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup; + int mu = nr_get_prach_mu(msgacc, rach_ConfigCommon); // prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4 get_nr_prach_occasion_info_from_index(config_index, @@ -266,7 +271,8 @@ static void schedule_nr_MsgA_pusch(NR_UplinkConfigCommon_t *uplinkConfigCommon, NR_MsgA_PUSCH_Resource_r16_t *msgA_PUSCH_Resource = uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice .setup->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16; - int mu = nr_get_mu(uplinkConfigCommon); + int mu = nr_get_prach_mu(uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup, + uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup); const int n_slots_frame = nr_slots_per_frame[mu]; slot_t msgA_pusch_slot = (slotP + msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16) % n_slots_frame; @@ -367,7 +373,10 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP NR_COMMON_channels_t *cc = gNB->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - int mu = nr_get_mu(scc->uplinkConfigCommon); + NR_MsgA_ConfigCommon_r16_t *msgacc = NULL; + if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 && scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16) + msgacc = scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup; + int mu = nr_get_prach_mu(msgacc, rach_ConfigCommon); int index = ul_buffer_index(frameP, slotP, mu, gNB->UL_tti_req_ahead_size); nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[0][index]; nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0]; From c7e9d687c66603a9824f84aa4f45d34e2282e08c Mon Sep 17 00:00:00 2001 From: ndomingues Date: Fri, 11 Oct 2024 10:05:51 +0100 Subject: [PATCH 15/15] Set msg1_SubcarrierSpacing to the same value as the UL SCS 3GPP 38.331: If absent, the UE applies the SCS as derived from the prach-ConfigurationIndex in RACH-ConfigGeneric (see tables Table 6.3.3.1-1, Table 6.3.3.1-2, Table 6.3.3.2-2 and Table 6.3.3.2-3, TS 38.211 [16]). This procedure for msg1_SubcarrierSpacing NULL is not implemented, so we aplly the same value of UL SCS. --- openair2/GNB_APP/gnb_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 51913209c9..4b7dccab3f 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -288,7 +288,7 @@ void fill_scc_sim(NR_ServingCellConfigCommon_t *scc, uint64_t *ssb_bitmap, int N rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present = NR_RACH_ConfigCommon__prach_RootSequenceIndex_PR_l139; rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139 = 0; rach_ConfigCommon->choice.setup->restrictedSetConfig = NR_RACH_ConfigCommon__restrictedSetConfig_unrestrictedSet; - *rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing = -1; + *rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing = mu_ul; struct NR_SetupRelease_PUSCH_ConfigCommon *pusch_ConfigCommon = initialUplinkBWP->pusch_ConfigCommon; asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, add_PUSCH_TimeDomainResourceAllocation(55));