Commit 75af74c7 authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/RA_2-Step' into integration_2024_w41

parents eccecde2 c7e9d687
......@@ -54,6 +54,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 */ \
......
......@@ -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)
......
......@@ -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,
......
......@@ -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;}
......
......@@ -90,6 +90,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"
......@@ -295,4 +311,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
......@@ -150,6 +150,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)
......@@ -271,7 +293,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));
......@@ -389,6 +411,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;
......@@ -940,14 +970,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 "
......
......@@ -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;
......@@ -559,6 +613,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;
......@@ -629,5 +684,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__ */
......@@ -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);
......@@ -5313,6 +5314,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)
......@@ -5323,3 +5333,20 @@ int get_FeedbackDisabled(NR_DownlinkHARQ_FeedbackDisabled_r17_t *downlinkHARQ_Fe
return (downlinkHARQ_FeedbackDisabled_r17->buf[byte_index] >> (7 - bit_index)) & 1;
}
int nr_get_prach_mu(const NR_MsgA_ConfigCommon_r16_t *msgacc, const NR_RACH_ConfigCommon_t *rach_ConfigCommon)
{
int mu;
// if 2-Step configuration file exists
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;
}
......@@ -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);
......@@ -325,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_prach_mu(const NR_MsgA_ConfigCommon_r16_t *msgacc, const NR_RACH_ConfigCommon_t *rach_ConfigCommon);
#endif
......@@ -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,
......
......@@ -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;
......@@ -268,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
......@@ -299,7 +295,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,10 +308,21 @@ 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;
/// 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
......
......@@ -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);
......
......@@ -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) {
......
......@@ -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) {
......@@ -3434,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
......@@ -3457,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.
......@@ -3475,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
......@@ -3618,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);
......
......@@ -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++;
}
......@@ -1739,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){
......@@ -1765,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);
......@@ -2867,7 +2926,54 @@ 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) {
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 =
(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
}
......
......@@ -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;
......
......@@ -2469,10 +2469,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));
......
......@@ -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++;
}
......
......@@ -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);
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;
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]);
}
......@@ -914,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);
......@@ -949,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;
}
}
......@@ -1787,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);
......
......@@ -113,16 +113,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_MsgB_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;
......@@ -221,6 +223,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
......@@ -249,6 +253,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
......@@ -755,7 +760,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;
......
......@@ -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;
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment