Merge remote-tracking branch 'origin/fix-ue-dlsch' into integration_2022_wk17
This commit is contained in:
@@ -58,11 +58,6 @@ extern int l2_init_eNB(void);
|
||||
extern void mac_top_init_eNB(void);
|
||||
extern void mac_init_cell_params(int Mod_idP,int CC_idP);
|
||||
|
||||
|
||||
int32_t **rxdata;
|
||||
int32_t **txdata;
|
||||
|
||||
|
||||
typedef struct eutra_bandentry_s {
|
||||
int16_t band;
|
||||
uint32_t ul_min;
|
||||
|
||||
@@ -107,11 +107,10 @@ typedef struct {
|
||||
} __attribute__ ((__packed__)) NR_MAC_SUBHEADER_SHORT;
|
||||
|
||||
typedef struct {
|
||||
uint8_t LCID: 6; // octet 1 [5:0]
|
||||
uint8_t F: 1; // octet 1 [6]
|
||||
uint8_t R: 1; // octet 1 [7]
|
||||
uint8_t L1: 8; // octet 2 [7:0]
|
||||
uint8_t L2: 8; // octet 3 [7:0]
|
||||
uint8_t LCID: 6;
|
||||
uint8_t F: 1;
|
||||
uint8_t R: 1;
|
||||
uint16_t L: 16;
|
||||
} __attribute__ ((__packed__)) NR_MAC_SUBHEADER_LONG;
|
||||
|
||||
typedef struct {
|
||||
@@ -119,6 +118,23 @@ typedef struct {
|
||||
uint8_t R: 2; // octet 1 [7:6]
|
||||
} __attribute__ ((__packed__)) NR_MAC_SUBHEADER_FIXED;
|
||||
|
||||
static inline int get_mac_len(uint8_t* pdu, int pdu_len, uint16_t *mac_ce_len, uint16_t *mac_subheader_len) {
|
||||
if ( pdu_len < sizeof(NR_MAC_SUBHEADER_SHORT))
|
||||
return false;
|
||||
NR_MAC_SUBHEADER_SHORT *s = (NR_MAC_SUBHEADER_SHORT*) pdu;
|
||||
NR_MAC_SUBHEADER_LONG *l = (NR_MAC_SUBHEADER_LONG*) pdu;
|
||||
if (s->F && pdu_len < sizeof(NR_MAC_SUBHEADER_LONG))
|
||||
return false;
|
||||
if (s->F) {
|
||||
*mac_subheader_len = sizeof(*l);
|
||||
*mac_ce_len = ntohs(l->L);
|
||||
} else {
|
||||
*mac_subheader_len = sizeof(*s);
|
||||
*mac_ce_len = s->L;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// BSR MAC CEs
|
||||
// TS 38.321 ch. 6.1.3.1
|
||||
// Short BSR for a specific logical channel group ID
|
||||
|
||||
@@ -2137,6 +2137,7 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac,
|
||||
pucch->is_common = current_harq->is_common;
|
||||
current_harq->active = false;
|
||||
current_harq->ack_received = false;
|
||||
LOG_D(PHY,"%4d.%2d Sent %d ack on harq pid %d\n", frame, slot, current_harq->ack, dl_harq_pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3370,10 +3371,6 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
NR_UL_TIME_ALIGNMENT_t *ul_time_alignment,
|
||||
int pdu_id){
|
||||
|
||||
uint8_t rx_lcid;
|
||||
uint16_t mac_ce_len;
|
||||
uint16_t mac_subheader_len;
|
||||
uint16_t mac_sdu_len;
|
||||
module_id_t module_idP = dl_info->module_id;
|
||||
frame_t frameP = dl_info->frame;
|
||||
int slot = dl_info->slot;
|
||||
@@ -3392,139 +3389,100 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
LOG_D(MAC, "In %s [%d.%d]: processing PDU %d (with length %d) of %d total number of PDUs...\n", __FUNCTION__, frameP, slot, pdu_id, pdu_len, dl_info->rx_ind->number_pdus);
|
||||
|
||||
while (!done && pdu_len > 0){
|
||||
mac_ce_len = 0x0000;
|
||||
mac_subheader_len = 0x0001; // default to fixed-length subheader = 1-oct
|
||||
mac_sdu_len = 0x0000;
|
||||
rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID;
|
||||
uint16_t mac_len = 0x0000;
|
||||
uint16_t mac_subheader_len = 0x0001; // default to fixed-length subheader = 1-oct
|
||||
uint8_t rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID;
|
||||
|
||||
LOG_D(MAC, "[UE] LCID %d, PDU length %d\n", rx_lcid, pdu_len);
|
||||
bool ret;
|
||||
switch(rx_lcid){
|
||||
// MAC CE
|
||||
case DL_SCH_LCID_CCCH:
|
||||
// MSG4 RRC Setup 38.331
|
||||
// variable length
|
||||
if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){
|
||||
mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *) pduP)->L1 & 0x7f) << 8)
|
||||
| ((uint16_t)((NR_MAC_SUBHEADER_LONG *) pduP)->L2 & 0xff);
|
||||
mac_subheader_len = 3;
|
||||
} else {
|
||||
mac_sdu_len = ((NR_MAC_SUBHEADER_SHORT *) pduP)->L;
|
||||
mac_subheader_len = 2;
|
||||
}
|
||||
|
||||
AssertFatal(pdu_len > mac_sdu_len, "The mac_sdu_len (%d) has an invalid size. PDU len = %d! \n",
|
||||
mac_sdu_len, pdu_len);
|
||||
ret=get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len);
|
||||
AssertFatal(ret, "The mac_len (%d) has an invalid size. PDU len = %d! \n",
|
||||
mac_len, pdu_len);
|
||||
|
||||
// Check if it is a valid CCCH message, we get all 00's messages very often
|
||||
int i = 0;
|
||||
for(i=0; i<(mac_subheader_len+mac_sdu_len); i++) {
|
||||
for(i=0; i<(mac_subheader_len+mac_len); i++) {
|
||||
if(pduP[i] != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == (mac_subheader_len+mac_sdu_len)) {
|
||||
if (i == (mac_subheader_len+mac_len)) {
|
||||
LOG_D(NR_MAC, "%s() Invalid CCCH message!, pdu_len: %d\n", __func__, pdu_len);
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( mac_sdu_len > 0 ) {
|
||||
LOG_D(NR_MAC,"DL_SCH_LCID_CCCH (e.g. RRCSetup) with payload len %d\n", mac_sdu_len);
|
||||
if ( mac_len > 0 ) {
|
||||
LOG_D(NR_MAC,"DL_SCH_LCID_CCCH (e.g. RRCSetup) with payload len %d\n", mac_len);
|
||||
for (int i = 0; i < mac_subheader_len; i++) {
|
||||
LOG_D(NR_MAC, "MAC header %d: 0x%x\n", i, pduP[i]);
|
||||
}
|
||||
for (int i = 0; i < mac_sdu_len; i++) {
|
||||
for (int i = 0; i < mac_len; i++) {
|
||||
LOG_D(NR_MAC, "%d: 0x%x\n", i, pduP[mac_subheader_len + i]);
|
||||
}
|
||||
nr_mac_rrc_data_ind_ue(module_idP, CC_id, gNB_index, frameP, 0, mac->crnti, CCCH, pduP+mac_subheader_len, mac_sdu_len);
|
||||
nr_mac_rrc_data_ind_ue(module_idP, CC_id, gNB_index, frameP, 0, mac->crnti, CCCH, pduP+mac_subheader_len, mac_len);
|
||||
}
|
||||
break;
|
||||
case DL_SCH_LCID_TCI_STATE_ACT_UE_SPEC_PDSCH:
|
||||
case DL_SCH_LCID_APERIODIC_CSI_TRI_STATE_SUBSEL:
|
||||
case DL_SCH_LCID_SP_CSI_RS_CSI_IM_RES_SET_ACT:
|
||||
case DL_SCH_LCID_SP_SRS_ACTIVATION:
|
||||
|
||||
// 38.321 Ch6.1.3.14
|
||||
// varialbe length
|
||||
mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L;
|
||||
mac_subheader_len = 2;
|
||||
if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){
|
||||
mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8;
|
||||
mac_subheader_len = 3;
|
||||
}
|
||||
break;
|
||||
case DL_SCH_LCID_APERIODIC_CSI_TRI_STATE_SUBSEL:
|
||||
// 38.321 Ch6.1.3.13
|
||||
// varialbe length
|
||||
mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L;
|
||||
mac_subheader_len = 2;
|
||||
if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){
|
||||
mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8;
|
||||
mac_subheader_len = 3;
|
||||
}
|
||||
break;
|
||||
case DL_SCH_LCID_SP_CSI_RS_CSI_IM_RES_SET_ACT:
|
||||
// 38.321 Ch6.1.3.12
|
||||
// varialbe length
|
||||
mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L;
|
||||
mac_subheader_len = 2;
|
||||
if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){
|
||||
mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8;
|
||||
mac_subheader_len = 3;
|
||||
}
|
||||
break;
|
||||
case DL_SCH_LCID_SP_SRS_ACTIVATION:
|
||||
// 38.321 Ch6.1.3.17
|
||||
// varialbe length
|
||||
mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L;
|
||||
mac_subheader_len = 2;
|
||||
if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){
|
||||
mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8;
|
||||
mac_subheader_len = 3;
|
||||
}
|
||||
get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len);
|
||||
break;
|
||||
|
||||
case DL_SCH_LCID_RECOMMENDED_BITRATE:
|
||||
// 38.321 Ch6.1.3.20
|
||||
mac_ce_len = 2;
|
||||
mac_len = 2;
|
||||
break;
|
||||
case DL_SCH_LCID_SP_ZP_CSI_RS_RES_SET_ACT:
|
||||
// 38.321 Ch6.1.3.19
|
||||
mac_ce_len = 2;
|
||||
mac_len = 2;
|
||||
break;
|
||||
case DL_SCH_LCID_PUCCH_SPATIAL_RELATION_ACT:
|
||||
// 38.321 Ch6.1.3.18
|
||||
mac_ce_len = 3;
|
||||
mac_len = 3;
|
||||
break;
|
||||
case DL_SCH_LCID_SP_CSI_REP_PUCCH_ACT:
|
||||
// 38.321 Ch6.1.3.16
|
||||
mac_ce_len = 2;
|
||||
mac_len = 2;
|
||||
break;
|
||||
case DL_SCH_LCID_TCI_STATE_IND_UE_SPEC_PDCCH:
|
||||
// 38.321 Ch6.1.3.15
|
||||
mac_ce_len = 2;
|
||||
mac_len = 2;
|
||||
break;
|
||||
case DL_SCH_LCID_DUPLICATION_ACT:
|
||||
// 38.321 Ch6.1.3.11
|
||||
mac_ce_len = 1;
|
||||
mac_len = 1;
|
||||
break;
|
||||
case DL_SCH_LCID_SCell_ACT_4_OCT:
|
||||
// 38.321 Ch6.1.3.10
|
||||
mac_ce_len = 4;
|
||||
mac_len = 4;
|
||||
break;
|
||||
case DL_SCH_LCID_SCell_ACT_1_OCT:
|
||||
// 38.321 Ch6.1.3.10
|
||||
mac_ce_len = 1;
|
||||
mac_len = 1;
|
||||
break;
|
||||
case DL_SCH_LCID_L_DRX:
|
||||
// 38.321 Ch6.1.3.6
|
||||
// fixed length but not yet specify.
|
||||
mac_ce_len = 0;
|
||||
mac_len = 0;
|
||||
break;
|
||||
case DL_SCH_LCID_DRX:
|
||||
// 38.321 Ch6.1.3.5
|
||||
// fixed length but not yet specify.
|
||||
mac_ce_len = 0;
|
||||
mac_len = 0;
|
||||
break;
|
||||
case DL_SCH_LCID_TA_COMMAND:
|
||||
// 38.321 Ch6.1.3.4
|
||||
mac_ce_len = 1;
|
||||
mac_len = 1;
|
||||
|
||||
/*uint8_t ta_command = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND;
|
||||
uint8_t tag_id = ((NR_MAC_CE_TA *)pduP)[1].TAGID;*/
|
||||
@@ -3546,14 +3504,14 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
// Clause 5.1.5 and 6.1.3.3 of 3GPP TS 38.321 version 16.2.1 Release 16
|
||||
// MAC Header: 1 byte (R/R/LCID)
|
||||
// MAC SDU: 6 bytes (UE Contention Resolution Identity)
|
||||
mac_ce_len = 6;
|
||||
mac_len = 6;
|
||||
|
||||
if(ra->ra_state == WAIT_CONTENTION_RESOLUTION) {
|
||||
LOG_I(MAC, "[UE %d][RAPROC] Frame %d : received contention resolution identity: 0x%02x%02x%02x%02x%02x%02x Terminating RA procedure\n",
|
||||
module_idP, frameP, pduP[1], pduP[2], pduP[3], pduP[4], pduP[5], pduP[6]);
|
||||
|
||||
bool ra_success = true;
|
||||
for(int i = 0; i<mac_ce_len; i++) {
|
||||
for(int i = 0; i<mac_len; i++) {
|
||||
if(ra->cont_res_id[i] != pduP[i+1]) {
|
||||
ra_success = false;
|
||||
break;
|
||||
@@ -3581,25 +3539,9 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
// check if LCID is valid at current time.
|
||||
default:
|
||||
{
|
||||
// check if LCID is valid at current time.
|
||||
if (pdu_len < sizeof(NR_MAC_SUBHEADER_SHORT))
|
||||
return;
|
||||
NR_MAC_SUBHEADER_SHORT *shs = (NR_MAC_SUBHEADER_SHORT *)pduP;
|
||||
if (shs->F) {
|
||||
//mac_sdu_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8;
|
||||
mac_subheader_len = 3;
|
||||
if (pdu_len < sizeof(NR_MAC_SUBHEADER_LONG))
|
||||
return;
|
||||
NR_MAC_SUBHEADER_LONG *shl = (NR_MAC_SUBHEADER_LONG *)pduP;
|
||||
mac_sdu_len = ((uint16_t)(shl->L1 & 0x7f) << 8) | (uint16_t)(shl->L2 & 0xff);
|
||||
} else {
|
||||
if (pdu_len < sizeof(NR_MAC_SUBHEADER_SHORT))
|
||||
return;
|
||||
mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L;
|
||||
mac_subheader_len = 2;
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC, "[UE %d] Frame %d : DLSCH -> DL-DTCH %d (gNB %d, %d bytes)\n", module_idP, frameP, rx_lcid, gNB_index, mac_sdu_len);
|
||||
if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len))
|
||||
return;
|
||||
LOG_D(NR_MAC, "[UE %d] %4d.%2d : DLSCH -> DL-DTCH %d (gNB %d, %d bytes)\n", module_idP, frameP, slot, rx_lcid, gNB_index, mac_len);
|
||||
|
||||
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
|
||||
LOG_T(MAC, "[UE %d] First 32 bytes of DLSCH : \n", module_idP);
|
||||
@@ -3620,7 +3562,7 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
MBMS_FLAG_NO,
|
||||
rx_lcid,
|
||||
(char *) (pduP + mac_subheader_len),
|
||||
mac_sdu_len,
|
||||
mac_len,
|
||||
1,
|
||||
NULL);
|
||||
} else {
|
||||
@@ -3631,8 +3573,8 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
break;
|
||||
}
|
||||
}
|
||||
pduP += ( mac_subheader_len + mac_ce_len + mac_sdu_len );
|
||||
pdu_len -= ( mac_subheader_len + mac_ce_len + mac_sdu_len );
|
||||
pduP += ( mac_subheader_len + mac_len );
|
||||
pdu_len -= ( mac_subheader_len + mac_len );
|
||||
if (pdu_len < 0)
|
||||
LOG_E(MAC, "[UE %d][%d.%d] nr_ue_process_mac_pdu, residual mac pdu length %d < 0!\n", module_idP, frameP, slot, pdu_len);
|
||||
}
|
||||
|
||||
@@ -3143,8 +3143,7 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP,
|
||||
header->R = 0;
|
||||
header->F = 1;
|
||||
header->LCID = lcid;
|
||||
header->L1 = ((unsigned short) sdu_length >> 8) & 0x7f;
|
||||
header->L2 = (unsigned short) sdu_length & 0xff;
|
||||
header->L = htons(sdu_length);
|
||||
|
||||
#ifdef ENABLE_MAC_PAYLOAD_DEBUG
|
||||
LOG_I(NR_MAC, "In %s: dumping MAC sub-header with length %d: \n", __FUNCTION__, sh_size);
|
||||
|
||||
@@ -1622,7 +1622,7 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra
|
||||
harq->feedback_slot = pucch->ul_slot;
|
||||
harq->feedback_frame = pucch->frame;
|
||||
|
||||
uint8_t *buf = (uint8_t *) harq->tb;
|
||||
uint8_t *buf = (uint8_t *) harq->transportBlock;
|
||||
// Bytes to be transmitted
|
||||
if (harq->round == 0) {
|
||||
if (ra->msg3_dcch_dtch) {
|
||||
@@ -1870,11 +1870,11 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra
|
||||
}
|
||||
|
||||
T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(ra->rnti),
|
||||
T_INT(frameP), T_INT(slotP), T_INT(current_harq_pid), T_BUFFER(harq->tb, harq->tb_size));
|
||||
T_INT(frameP), T_INT(slotP), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock, harq->tb_size));
|
||||
|
||||
// DL TX request
|
||||
nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs];
|
||||
memcpy(tx_req->TLVs[0].value.direct, harq->tb, sizeof(uint8_t) * harq->tb_size);
|
||||
memcpy(tx_req->TLVs[0].value.direct, harq->transportBlock, sizeof(uint8_t) * harq->tb_size);
|
||||
tx_req->PDU_length = harq->tb_size;
|
||||
tx_req->PDU_index = pduindex;
|
||||
tx_req->num_TLV = 1;
|
||||
|
||||
@@ -53,10 +53,10 @@
|
||||
#define WORD 32
|
||||
//#define SIZE_OF_POINTER sizeof (void *)
|
||||
|
||||
void calculate_preferred_dl_tda(module_id_t module_id, const NR_BWP_Downlink_t *bwp)
|
||||
{
|
||||
void calculate_preferred_dl_tda(module_id_t module_id, const NR_BWP_Downlink_t *bwp) {
|
||||
gNB_MAC_INST *nrmac = RC.nrmac[module_id];
|
||||
const int bwp_id = bwp ? bwp->bwp_Id : 0;
|
||||
|
||||
if (nrmac->preferred_dl_tda[bwp_id])
|
||||
return;
|
||||
|
||||
@@ -65,27 +65,27 @@ void calculate_preferred_dl_tda(module_id_t module_id, const NR_BWP_Downlink_t *
|
||||
lte_frame_type_t frame_type = nrmac->common_channels->frame_type;
|
||||
const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd =
|
||||
scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
|
||||
scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
int symb_dlMixed = 0;
|
||||
int nr_mix_slots = 0;
|
||||
int nr_slots_period = n;
|
||||
|
||||
if (tdd) {
|
||||
symb_dlMixed = (1 << tdd->nrofDownlinkSymbols) - 1;
|
||||
nr_mix_slots = tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0;
|
||||
nr_slots_period /= get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
|
||||
}
|
||||
else
|
||||
} else
|
||||
// if TDD configuration is not present and the band is not FDD, it means it is a dynamic TDD configuration
|
||||
AssertFatal(nrmac->common_channels->frame_type == FDD,"Dynamic TDD not handled yet\n");
|
||||
|
||||
int target_ss;
|
||||
|
||||
if (bwp) {
|
||||
target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
target_ss = NR_SearchSpace__searchSpaceType_PR_common;
|
||||
}
|
||||
|
||||
const NR_SIB1_t *sib1 = nrmac->common_channels[0].sib1 ? nrmac->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL;
|
||||
NR_SearchSpace_t *search_space = get_searchspace(sib1,
|
||||
scc,
|
||||
@@ -113,9 +113,9 @@ void calculate_preferred_dl_tda(module_id_t module_id, const NR_BWP_Downlink_t *
|
||||
// here we assume that the coreset is scheduled every slot (which it
|
||||
// currently is) and starting at symbol 0
|
||||
AssertFatal((symb_coreset & symb_tda) == 0, "TDA index 0 for DL overlaps with CORESET\n");
|
||||
|
||||
/* check that TDA index 1 fits into DL part of mixed slot, if it exists */
|
||||
int tdaMi = -1;
|
||||
|
||||
if (frame_type == TDD && tdaList->list.count > 1) {
|
||||
const NR_PDSCH_TimeDomainResourceAllocation_t *tdaP_Mi = tdaList->list.array[1];
|
||||
AssertFatal(!tdaP_Mi->k0 || *tdaP_Mi->k0 == 0,
|
||||
@@ -124,6 +124,7 @@ void calculate_preferred_dl_tda(module_id_t module_id, const NR_BWP_Downlink_t *
|
||||
int start, len;
|
||||
SLIV2SL(tdaP_Mi->startSymbolAndLength, &start, &len);
|
||||
const uint16_t symb_tda = ((1 << len) - 1) << start;
|
||||
|
||||
// check whether coreset and TDA overlap: then, we cannot use it. Also,
|
||||
// check whether TDA is entirely within mixed slot DL. Note that
|
||||
// here we assume that the coreset is scheduled every slot (which it
|
||||
@@ -143,10 +144,12 @@ void calculate_preferred_dl_tda(module_id_t module_id, const NR_BWP_Downlink_t *
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
nrmac->preferred_dl_tda[bwp_id][i] = -1;
|
||||
|
||||
if (frame_type == FDD || i % nr_slots_period < tdd->nrofDownlinkSlots)
|
||||
nrmac->preferred_dl_tda[bwp_id][i] = 0;
|
||||
else if (nr_mix_slots && i % nr_slots_period == tdd->nrofDownlinkSlots)
|
||||
nrmac->preferred_dl_tda[bwp_id][i] = tdaMi;
|
||||
|
||||
LOG_D(MAC, "slot %d preferred_dl_tda %d\n", i, nrmac->preferred_dl_tda[bwp_id][i]);
|
||||
}
|
||||
}
|
||||
@@ -157,8 +160,7 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP,
|
||||
const NR_UE_sched_ctrl_t *ue_sched_ctl,
|
||||
unsigned char *mac_pdu,
|
||||
unsigned char drx_cmd,
|
||||
unsigned char *ue_cont_res_id)
|
||||
{
|
||||
unsigned char *ue_cont_res_id) {
|
||||
gNB_MAC_INST *gNB = RC.nrmac[module_idP];
|
||||
NR_MAC_SUBHEADER_FIXED *mac_pdu_ptr = (NR_MAC_SUBHEADER_FIXED *) mac_pdu;
|
||||
uint8_t last_size = 0;
|
||||
@@ -201,8 +203,6 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP,
|
||||
memcpy((void *) mac_pdu_ptr, (void *) ce_ptr, mac_ce_size);
|
||||
ce_ptr += mac_ce_size;
|
||||
mac_pdu_ptr += (unsigned char) mac_ce_size;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Contention resolution fixed subheader and MAC CE
|
||||
@@ -399,18 +399,18 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP,
|
||||
|
||||
#define BLER_UPDATE_FRAME 10
|
||||
#define BLER_FILTER 0.9f
|
||||
int get_mcs_from_bler(module_id_t mod_id, int CC_id, frame_t frame, sub_frame_t slot, int UE_id, int mcs_table)
|
||||
{
|
||||
int get_mcs_from_bler(module_id_t mod_id, int CC_id, frame_t frame, sub_frame_t slot, int UE_id, int mcs_table) {
|
||||
gNB_MAC_INST *nrmac = RC.nrmac[mod_id];
|
||||
const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon;
|
||||
const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||
|
||||
int max_allowed_mcs = (mcs_table == 1) ? 27 : 28;
|
||||
int max_mcs = nrmac->dl_max_mcs;
|
||||
|
||||
if (nrmac->dl_max_mcs>max_allowed_mcs)
|
||||
max_mcs = max_allowed_mcs;
|
||||
|
||||
NR_DL_bler_stats_t *bler_stats = &nrmac->UE_info.UE_sched_ctrl[UE_id].dl_bler_stats;
|
||||
|
||||
/* first call: everything is zero. Initialize to sensible default */
|
||||
if (bler_stats->last_frame_slot == 0 && bler_stats->mcs == 0) {
|
||||
bler_stats->last_frame_slot = frame * n + slot;
|
||||
@@ -418,13 +418,16 @@ int get_mcs_from_bler(module_id_t mod_id, int CC_id, frame_t frame, sub_frame_t
|
||||
bler_stats->bler = (nrmac->dl_bler_target_lower + nrmac->dl_bler_target_upper) / 2;
|
||||
bler_stats->rd2_bler = nrmac->dl_rd2_bler_threshold;
|
||||
}
|
||||
|
||||
const int now = frame * n + slot;
|
||||
int diff = now - bler_stats->last_frame_slot;
|
||||
|
||||
if (diff < 0) // wrap around
|
||||
diff += 1024 * n;
|
||||
|
||||
const uint8_t old_mcs = bler_stats->mcs;
|
||||
const NR_mac_stats_t *stats = &nrmac->UE_info.mac_stats[UE_id];
|
||||
|
||||
// TODO put back this condition when relevant
|
||||
/*const int dret3x = stats->dlsch_rounds[3] - bler_stats->dlsch_rounds[3];
|
||||
if (dret3x > 0) {
|
||||
@@ -447,8 +450,8 @@ int get_mcs_from_bler(module_id_t mod_id, int CC_id, frame_t frame, sub_frame_t
|
||||
const float rd2_bler_wnd = dtx > 0 ? (float) dretx2 / dtx : bler_stats->rd2_bler;
|
||||
bler_stats->bler = BLER_FILTER * bler_stats->bler + (1 - BLER_FILTER) * bler_window;
|
||||
bler_stats->rd2_bler = BLER_FILTER / 4 * bler_stats->rd2_bler + (1 - BLER_FILTER / 4) * rd2_bler_wnd;
|
||||
|
||||
int new_mcs = old_mcs;
|
||||
|
||||
// TODO put back this condition when relevant
|
||||
/* first ensure that number of 2nd retx is below threshold. If this is the
|
||||
* case, use 1st retx to adjust faster
|
||||
@@ -459,9 +462,8 @@ int get_mcs_from_bler(module_id_t mod_id, int CC_id, frame_t frame, sub_frame_t
|
||||
new_mcs += 1;
|
||||
else if (bler_stats->bler > nrmac->dl_bler_target_upper && old_mcs > 6)
|
||||
new_mcs -= 1;
|
||||
|
||||
// else we are within threshold boundaries
|
||||
|
||||
|
||||
bler_stats->last_frame_slot = now;
|
||||
bler_stats->mcs = new_mcs;
|
||||
memcpy(bler_stats->dlsch_rounds, stats->dlsch_rounds, sizeof(stats->dlsch_rounds));
|
||||
@@ -473,11 +475,9 @@ int get_mcs_from_bler(module_id_t mod_id, int CC_id, frame_t frame, sub_frame_t
|
||||
void nr_store_dlsch_buffer(module_id_t module_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot) {
|
||||
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
|
||||
|
||||
for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
|
||||
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
sched_ctrl->num_total_bytes = 0;
|
||||
sched_ctrl->dl_pdus_total = 0;
|
||||
@@ -485,21 +485,20 @@ void nr_store_dlsch_buffer(module_id_t module_id,
|
||||
/* loop over all activated logical channels */
|
||||
// Note: DL_SCH_LCID_DCCH, DL_SCH_LCID_DCCH1, DL_SCH_LCID_DTCH
|
||||
for (int i = 0; i < sched_ctrl->dl_lc_num; ++i) {
|
||||
|
||||
const int lcid = sched_ctrl->dl_lc_ids[i];
|
||||
const uint16_t rnti = UE_info->rnti[UE_id];
|
||||
LOG_D(NR_MAC, "In %s: UE %d/%x: LCID %d\n", __FUNCTION__, UE_id, rnti, lcid);
|
||||
start_meas(&RC.nrmac[module_id]->rlc_status_ind);
|
||||
sched_ctrl->rlc_status[lcid] = mac_rlc_status_ind(module_id,
|
||||
rnti,
|
||||
module_id,
|
||||
frame,
|
||||
slot,
|
||||
ENB_FLAG_YES,
|
||||
MBMS_FLAG_NO,
|
||||
lcid,
|
||||
0,
|
||||
0);
|
||||
rnti,
|
||||
module_id,
|
||||
frame,
|
||||
slot,
|
||||
ENB_FLAG_YES,
|
||||
MBMS_FLAG_NO,
|
||||
lcid,
|
||||
0,
|
||||
0);
|
||||
stop_meas(&RC.nrmac[module_id]->rlc_status_ind);
|
||||
|
||||
if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0)
|
||||
@@ -531,6 +530,7 @@ bool allocate_dl_retransmission(module_id_t module_id,
|
||||
int UE_id,
|
||||
int current_harq_pid) {
|
||||
|
||||
|
||||
gNB_MAC_INST *nr_mac = RC.nrmac[module_id];
|
||||
const NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels->ServingCellConfigCommon;
|
||||
NR_UE_info_t *UE_info = &nr_mac->UE_info;
|
||||
@@ -558,30 +558,34 @@ bool allocate_dl_retransmission(module_id_t module_id,
|
||||
|
||||
const int coresetid = (sched_ctrl->active_bwp||bwpd) ? sched_ctrl->coreset->controlResourceSetId : RC.nrmac[module_id]->sched_ctrlCommon->coreset->controlResourceSetId;
|
||||
const uint16_t bwpSize = coresetid == 0 ? RC.nrmac[module_id]->cset0_bwp_size : NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
|
||||
|
||||
int rbStart = 0; // start wrt BWPstart
|
||||
|
||||
NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static;
|
||||
|
||||
int rbSize = 0;
|
||||
const int tda = RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Id : 0][slot];
|
||||
AssertFatal(tda>=0,"Unable to find PDSCH time domain allocation in list\n");
|
||||
|
||||
if (tda == retInfo->time_domain_allocation) {
|
||||
/* Check that there are enough resources for retransmission */
|
||||
while (rbSize < retInfo->rbSize) {
|
||||
rbStart += rbSize; /* last iteration rbSize was not enough, skip it */
|
||||
rbSize = 0;
|
||||
|
||||
while (rbStart < bwpSize &&
|
||||
!(rballoc_mask[rbStart]&SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols)))
|
||||
rbStart++;
|
||||
|
||||
if (rbStart >= bwpSize) {
|
||||
LOG_D(NR_MAC, "cannot allocate retransmission for UE %d/RNTI %04x: no resources\n", UE_id, UE_info->rnti[UE_id]);
|
||||
return false;
|
||||
}
|
||||
|
||||
while (rbStart + rbSize < bwpSize &&
|
||||
(rballoc_mask[rbStart + rbSize]&SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols)) &&
|
||||
rbSize < retInfo->rbSize)
|
||||
rbSize++;
|
||||
}
|
||||
|
||||
/* check whether we need to switch the TDA allocation since the last
|
||||
* (re-)transmission */
|
||||
if (ps->time_domain_allocation != tda || sched_ctrl->update_pdsch_ps) {
|
||||
@@ -599,8 +603,8 @@ bool allocate_dl_retransmission(module_id_t module_id,
|
||||
} else {
|
||||
/* the retransmission will use a different time domain allocation, check
|
||||
* that we have enough resources */
|
||||
|
||||
NR_pdsch_semi_static_t temp_ps = *ps;
|
||||
|
||||
nr_set_pdsch_semi_static(sib1,
|
||||
scc,
|
||||
UE_info->CellGroup[UE_id],
|
||||
@@ -613,6 +617,7 @@ bool allocate_dl_retransmission(module_id_t module_id,
|
||||
while (rbStart < bwpSize &&
|
||||
!(rballoc_mask[rbStart]&SL_to_bitmap(temp_ps.startSymbolIndex, temp_ps.nrOfSymbols)))
|
||||
rbStart++;
|
||||
|
||||
while (rbStart + rbSize < bwpSize &&
|
||||
(rballoc_mask[rbStart + rbSize]&SL_to_bitmap(temp_ps.startSymbolIndex, temp_ps.nrOfSymbols)))
|
||||
rbSize++;
|
||||
@@ -629,10 +634,12 @@ bool allocate_dl_retransmission(module_id_t module_id,
|
||||
rbSize,
|
||||
&new_tbs,
|
||||
&new_rbSize);
|
||||
|
||||
if (!success || new_tbs != retInfo->tb_size) {
|
||||
LOG_D(MAC, "%s(): new TBsize %d of new TDA does not match old TBS %d\n", __func__, new_tbs, retInfo->tb_size);
|
||||
LOG_D(MAC, "new TBsize %d of new TDA does not match old TBS %d\n", new_tbs, retInfo->tb_size);
|
||||
return false; /* the maximum TBsize we might have is smaller than what we need */
|
||||
}
|
||||
|
||||
/* we can allocate it. Overwrite the time_domain_allocation, the number
|
||||
* of RBs, and the new TB size. The rest is done below */
|
||||
retInfo->tb_size = new_tbs;
|
||||
@@ -645,12 +652,14 @@ bool allocate_dl_retransmission(module_id_t module_id,
|
||||
const int cid = sched_ctrl->coreset->controlResourceSetId;
|
||||
const uint16_t Y = get_Y(cid%3, slot, UE_info->rnti[UE_id]);
|
||||
uint8_t nr_of_candidates;
|
||||
|
||||
for (int i=0; i<5; i++) {
|
||||
// for now taking the lowest value among the available aggregation levels
|
||||
find_aggregation_candidates(&sched_ctrl->aggregation_level,
|
||||
&nr_of_candidates,
|
||||
sched_ctrl->search_space,
|
||||
1<<i);
|
||||
|
||||
if(nr_of_candidates>0) break;
|
||||
}
|
||||
|
||||
@@ -670,12 +679,12 @@ bool allocate_dl_retransmission(module_id_t module_id,
|
||||
|
||||
/* Find PUCCH occasion: if it fails, undo CCE allocation (undoing PUCCH
|
||||
* allocation after CCE alloc fail would be more complex) */
|
||||
|
||||
int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, sched_ctrl->active_ubwp, ubwpd, CCEIndex);
|
||||
const int alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot, r_pucch, 0);
|
||||
if (alloc<0) {
|
||||
LOG_D(MAC,
|
||||
"%s(): could not find PUCCH for UE %d/%04x@%d.%d\n",
|
||||
__func__,
|
||||
"could not find PUCCH for UE %d/%04x@%d.%d\n",
|
||||
UE_id,
|
||||
UE_info->rnti[UE_id],
|
||||
frame,
|
||||
@@ -685,23 +694,21 @@ bool allocate_dl_retransmission(module_id_t module_id,
|
||||
}
|
||||
|
||||
sched_ctrl->cce_index = CCEIndex;
|
||||
|
||||
fill_pdcch_vrb_map(RC.nrmac[module_id],
|
||||
/* CC_id = */ 0,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
CCEIndex,
|
||||
sched_ctrl->aggregation_level);
|
||||
|
||||
/* just reuse from previous scheduling opportunity, set new start RB */
|
||||
sched_ctrl->sched_pdsch = *retInfo;
|
||||
sched_ctrl->sched_pdsch.rbStart = rbStart;
|
||||
|
||||
sched_ctrl->sched_pdsch.pucch_allocation = alloc;
|
||||
|
||||
/* retransmissions: directly allocate */
|
||||
*n_rb_sched -= sched_ctrl->sched_pdsch.rbSize;
|
||||
|
||||
for (int rb = 0; rb < sched_ctrl->sched_pdsch.rbSize; rb++)
|
||||
rballoc_mask[rb + sched_ctrl->sched_pdsch.rbStart] ^= SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -715,7 +722,6 @@ void pf_dl(module_id_t module_id,
|
||||
int max_num_ue,
|
||||
int n_rb_sched,
|
||||
uint16_t *rballoc_mask) {
|
||||
|
||||
gNB_MAC_INST *mac = RC.nrmac[module_id];
|
||||
NR_UE_info_t *UE_info = &mac->UE_info;
|
||||
NR_ServingCellConfigCommon_t *scc=mac->common_channels[0].ServingCellConfigCommon;
|
||||
@@ -728,15 +734,16 @@ void pf_dl(module_id_t module_id,
|
||||
/* Loop UE_info->list to check retransmission */
|
||||
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||
if (UE_info->Msg4_ACKed[UE_id] != true) continue;
|
||||
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
|
||||
if (sched_ctrl->ul_failure==1 && get_softmodem_params()->phy_test==0) continue;
|
||||
|
||||
NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch;
|
||||
NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static;
|
||||
/* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */
|
||||
sched_pdsch->dl_harq_pid = sched_ctrl->retrans_dl_harq.head;
|
||||
|
||||
layers[UE_id] = ps->nrOfLayers; // initialization of layers to the previous value in the strcuture
|
||||
|
||||
/* Calculate Throughput */
|
||||
const float a = 0.0005f; // corresponds to 200ms window
|
||||
const uint32_t b = UE_info->mac_stats[UE_id].dlsch_current_bytes;
|
||||
@@ -746,13 +753,16 @@ void pf_dl(module_id_t module_id,
|
||||
if (sched_pdsch->dl_harq_pid >= 0) {
|
||||
/* Allocate retransmission */
|
||||
bool r = allocate_dl_retransmission(
|
||||
module_id, frame, slot, rballoc_mask, &n_rb_sched, UE_id, sched_pdsch->dl_harq_pid);
|
||||
module_id, frame, slot, rballoc_mask, &n_rb_sched, UE_id, sched_pdsch->dl_harq_pid);
|
||||
|
||||
if (!r) {
|
||||
LOG_D(NR_MAC, "%4d.%2d retransmission can NOT be allocated\n", frame, slot);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
|
||||
max_num_ue--;
|
||||
|
||||
if (max_num_ue < 0) return;
|
||||
} else {
|
||||
/* Check DL buffer and skip this UE if no bytes and no TA necessary */
|
||||
@@ -782,18 +792,21 @@ void pf_dl(module_id_t module_id,
|
||||
}
|
||||
|
||||
const int min_rbSize = 5;
|
||||
|
||||
/* Loop UE_sched to find max coeff and allocate transmission */
|
||||
while (max_num_ue > 0 && n_rb_sched >= min_rbSize && UE_sched.head >= 0) {
|
||||
|
||||
/* Find max coeff from UE_sched*/
|
||||
int *max = &UE_sched.head; /* assume head is max */
|
||||
int *p = &UE_sched.next[*max];
|
||||
|
||||
while (*p >= 0) {
|
||||
/* if the current one has larger coeff, save for later */
|
||||
if (coeff_ue[*p] > coeff_ue[*max])
|
||||
max = p;
|
||||
|
||||
p = &UE_sched.next[*p];
|
||||
}
|
||||
|
||||
/* remove the max one: do not use remove_nr_list() it goes through the
|
||||
* whole list every time. Note that UE_sched.tail might not be set
|
||||
* correctly anymore */
|
||||
@@ -803,6 +816,7 @@ void pf_dl(module_id_t module_id,
|
||||
*p = -1;
|
||||
NR_CellGroupConfig_t *cg = UE_info->CellGroup[UE_id];
|
||||
|
||||
|
||||
NR_BWP_DownlinkDedicated_t *bwpd =
|
||||
cg &&
|
||||
cg->spCellConfig &&
|
||||
@@ -837,12 +851,14 @@ void pf_dl(module_id_t module_id,
|
||||
const int cid = sched_ctrl->coreset->controlResourceSetId;
|
||||
const uint16_t Y = get_Y(cid%3, slot, UE_info->rnti[UE_id]);
|
||||
uint8_t nr_of_candidates;
|
||||
|
||||
for (int i=0; i<5; i++) {
|
||||
// for now taking the lowest value among the available aggregation levels
|
||||
find_aggregation_candidates(&sched_ctrl->aggregation_level,
|
||||
&nr_of_candidates,
|
||||
sched_ctrl->search_space,
|
||||
1<<i);
|
||||
|
||||
if(nr_of_candidates>0) break;
|
||||
}
|
||||
|
||||
@@ -861,12 +877,13 @@ void pf_dl(module_id_t module_id,
|
||||
|
||||
/* Find PUCCH occasion: if it fails, undo CCE allocation (undoing PUCCH
|
||||
* allocation after CCE alloc fail would be more complex) */
|
||||
|
||||
int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, sched_ctrl->active_ubwp, ubwpd, CCEIndex);
|
||||
const int alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot, r_pucch, 0);
|
||||
|
||||
if (alloc<0) {
|
||||
LOG_D(NR_MAC,
|
||||
"%s(): could not find PUCCH for UE %d/%04x@%d.%d\n",
|
||||
__func__,
|
||||
"could not find PUCCH for UE %d/%04x@%d.%d\n",
|
||||
UE_id,
|
||||
rnti,
|
||||
frame,
|
||||
@@ -879,21 +896,18 @@ void pf_dl(module_id_t module_id,
|
||||
* and PUCCH */
|
||||
max_num_ue--;
|
||||
AssertFatal(max_num_ue >= 0, "Illegal max_num_ue %d\n", max_num_ue);
|
||||
|
||||
sched_ctrl->cce_index = CCEIndex;
|
||||
|
||||
fill_pdcch_vrb_map(mac,
|
||||
/* CC_id = */ 0,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
CCEIndex,
|
||||
sched_ctrl->aggregation_level);
|
||||
|
||||
/* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
|
||||
max_num_ue--;
|
||||
|
||||
if (max_num_ue < 0) return;
|
||||
|
||||
/* MCS has been set above */
|
||||
|
||||
const int tda = RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Id : 0][slot];
|
||||
AssertFatal(tda>=0,"Unable to find PDSCH time domain allocation in list\n");
|
||||
NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch;
|
||||
@@ -913,12 +927,14 @@ void pf_dl(module_id_t module_id,
|
||||
}
|
||||
|
||||
const uint16_t slbitmap = SL_to_bitmap(ps->startSymbolIndex, ps->nrOfSymbols);
|
||||
|
||||
// Freq-demain allocation
|
||||
while (rbStart < bwpSize &&
|
||||
!(rballoc_mask[rbStart]&slbitmap))
|
||||
rbStart++;
|
||||
|
||||
uint16_t max_rbSize = 1;
|
||||
|
||||
while (rbStart + max_rbSize < bwpSize &&
|
||||
(rballoc_mask[rbStart + max_rbSize]&slbitmap))
|
||||
max_rbSize++;
|
||||
@@ -947,39 +963,41 @@ void pf_dl(module_id_t module_id,
|
||||
sched_pdsch->rbSize = rbSize;
|
||||
sched_pdsch->rbStart = rbStart;
|
||||
sched_pdsch->tb_size = TBS;
|
||||
|
||||
/* transmissions: directly allocate */
|
||||
n_rb_sched -= sched_pdsch->rbSize;
|
||||
|
||||
for (int rb = 0; rb < sched_pdsch->rbSize; rb++)
|
||||
rballoc_mask[rb + sched_pdsch->rbStart] ^= slbitmap;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot)
|
||||
{
|
||||
void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot) {
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
|
||||
|
||||
if (UE_info->num_UEs == 0)
|
||||
return;
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[0].ServingCellConfigCommon;
|
||||
const int CC_id = 0;
|
||||
|
||||
/* Get bwpSize and TDAfrom the first UE */
|
||||
/* This is temporary and it assumes all UEs have the same BWP and TDA*/
|
||||
int UE_id = UE_info->list.head;
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
const int bwp_id = sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Id : 0;
|
||||
|
||||
if (!RC.nrmac[module_id]->preferred_dl_tda[bwp_id])
|
||||
return;
|
||||
|
||||
const int tda = RC.nrmac[module_id]->preferred_dl_tda[bwp_id][slot];
|
||||
int startSymbolIndex, nrOfSymbols;
|
||||
const struct NR_PDSCH_TimeDomainResourceAllocationList *tdaList = sched_ctrl->active_bwp ?
|
||||
sched_ctrl->active_bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList :
|
||||
scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
|
||||
sched_ctrl->active_bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList :
|
||||
scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
|
||||
AssertFatal(tda < tdaList->list.count, "time_domain_allocation %d>=%d\n", tda, tdaList->list.count);
|
||||
const int startSymbolAndLength = tdaList->list.array[tda]->startSymbolAndLength;
|
||||
SLIV2SL(startSymbolAndLength, &startSymbolIndex, &nrOfSymbols);
|
||||
|
||||
|
||||
const NR_SIB1_t *sib1 = RC.nrmac[module_id]->common_channels[0].sib1 ? RC.nrmac[module_id]->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL;
|
||||
NR_BWP_t *genericParameters = get_dl_bwp_genericParameters(sched_ctrl->active_bwp,
|
||||
RC.nrmac[module_id]->common_channels[0].ServingCellConfigCommon,
|
||||
@@ -1000,19 +1018,20 @@ void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t
|
||||
uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map;
|
||||
uint16_t rballoc_mask[bwpSize];
|
||||
int n_rb_sched = 0;
|
||||
|
||||
for (int i = 0; i < bwpSize; i++) {
|
||||
// calculate mask: init with "NOT" vrb_map:
|
||||
// if any RB in vrb_map is blocked (1), the current RBG will be 0
|
||||
rballoc_mask[i] = (~vrb_map[i+BWPStart])&0x3fff; //bitwise not and 14 symbols
|
||||
|
||||
// if all the pdsch symbols are free
|
||||
if((rballoc_mask[i]&slbitmap) ==
|
||||
slbitmap)
|
||||
slbitmap)
|
||||
n_rb_sched++;
|
||||
}
|
||||
|
||||
/* Retrieve amount of data to send for this UE */
|
||||
nr_store_dlsch_buffer(module_id, frame, slot);
|
||||
|
||||
/* proportional fair scheduling algorithm */
|
||||
pf_dl(module_id,
|
||||
frame,
|
||||
@@ -1023,8 +1042,7 @@ void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t
|
||||
rballoc_mask);
|
||||
}
|
||||
|
||||
nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(module_id_t module_id, int CC_id)
|
||||
{
|
||||
nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(module_id_t module_id, int CC_id) {
|
||||
/* in the PF algorithm, we have to use the TBsize to compute the coefficient.
|
||||
* This would include the number of DMRS symbols, which in turn depends on
|
||||
* the time domain allocation. In case we are in a mixed slot, we do not want
|
||||
@@ -1034,16 +1052,17 @@ nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(module_id_t module_id, int CC_id)
|
||||
for (int mcs = 0; mcs < 29; ++mcs) {
|
||||
if (mcs > 27 && mcsTableIdx == 1)
|
||||
continue;
|
||||
|
||||
const uint8_t Qm = nr_get_Qm_dl(mcs, mcsTableIdx);
|
||||
const uint16_t R = nr_get_code_rate_dl(mcs, mcsTableIdx);
|
||||
pf_tbs[mcsTableIdx][mcs] = nr_compute_tbs(Qm,
|
||||
R,
|
||||
1, /* rbSize */
|
||||
10, /* hypothetical number of slots */
|
||||
0, /* N_PRB_DMRS * N_DMRS_SLOT */
|
||||
0 /* N_PRB_oh, 0 for initialBWP */,
|
||||
0 /* tb_scaling */,
|
||||
1 /* nrOfLayers */)
|
||||
R,
|
||||
1, /* rbSize */
|
||||
10, /* hypothetical number of slots */
|
||||
0, /* N_PRB_DMRS * N_DMRS_SLOT */
|
||||
0 /* N_PRB_oh, 0 for initialBWP */,
|
||||
0 /* tb_scaling */,
|
||||
1 /* nrOfLayers */)
|
||||
>> 3;
|
||||
}
|
||||
}
|
||||
@@ -1055,22 +1074,23 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot) {
|
||||
gNB_MAC_INST *gNB_mac = RC.nrmac[module_id];
|
||||
|
||||
if (!is_xlsch_in_slot(gNB_mac->dlsch_slot_bitmap[slot / 64], slot))
|
||||
return;
|
||||
|
||||
/* PREPROCESSOR */
|
||||
gNB_mac->pre_processor_dl(module_id, frame, slot);
|
||||
|
||||
const int CC_id = 0;
|
||||
NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon;
|
||||
NR_UE_info_t *UE_info = &gNB_mac->UE_info;
|
||||
|
||||
nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body;
|
||||
|
||||
NR_list_t *UE_list = &UE_info->list;
|
||||
|
||||
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
|
||||
if (sched_ctrl->ul_failure==1 && get_softmodem_params()->phy_test==0) continue;
|
||||
|
||||
NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch;
|
||||
UE_info->mac_stats[UE_id].dlsch_current_bytes = 0;
|
||||
NR_CellGroupConfig_t *cg = UE_info->CellGroup[UE_id];
|
||||
@@ -1085,7 +1105,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
* Possible improvement: take the periodicity from input file.
|
||||
* If such UE is not scheduled now, it will be by the preprocessor later.
|
||||
* If we add the CE, ta_apply will be reset */
|
||||
if (frame == (sched_ctrl->ta_frame + 10) % 1024){
|
||||
if (frame == (sched_ctrl->ta_frame + 10) % 1024) {
|
||||
sched_ctrl->ta_apply = true; /* the timer is reset once TA CE is scheduled */
|
||||
LOG_D(NR_MAC, "[UE %d][%d.%d] UL timing alignment procedures: setting flag for Timing Advance command\n", UE_id, frame, slot);
|
||||
}
|
||||
@@ -1094,19 +1114,17 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
continue;
|
||||
|
||||
const rnti_t rnti = UE_info->rnti[UE_id];
|
||||
|
||||
/* pre-computed PDSCH values that only change if time domain
|
||||
* allocation/DMRS parameters change. Updated in the preprocessor through
|
||||
* nr_set_pdsch_semi_static() */
|
||||
NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static;
|
||||
|
||||
/* POST processing */
|
||||
const uint8_t nrOfLayers = ps->nrOfLayers;
|
||||
const uint16_t R = sched_pdsch->R;
|
||||
const uint8_t Qm = sched_pdsch->Qm;
|
||||
const uint32_t TBS = sched_pdsch->tb_size;
|
||||
|
||||
int8_t current_harq_pid = sched_pdsch->dl_harq_pid;
|
||||
|
||||
if (current_harq_pid < 0) {
|
||||
/* PP has not selected a specific HARQ Process, get a new one */
|
||||
current_harq_pid = sched_ctrl->available_dl_harq.head;
|
||||
@@ -1124,6 +1142,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
else
|
||||
remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid);
|
||||
}
|
||||
|
||||
NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid];
|
||||
DevAssert(!harq->is_waiting);
|
||||
add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid);
|
||||
@@ -1132,8 +1151,8 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
harq->feedback_slot = pucch->ul_slot;
|
||||
harq->is_waiting = true;
|
||||
UE_info->mac_stats[UE_id].dlsch_rounds[harq->round]++;
|
||||
|
||||
LOG_D(NR_MAC,"%4d.%2d [DLSCH/PDSCH/PUCCH] UE %d RNTI %04x DCI L %d start %3d RBs %3d startSymbol %2d nb_symbol %2d dmrspos %x MCS %2d nrOfLayers %d TBS %4d HARQ PID %2d round %d RV %d NDI %d dl_data_to_ULACK %d (%d.%d) PUCCH allocation %d TPC %d\n",
|
||||
LOG_D(NR_MAC,
|
||||
"%4d.%2d [DLSCH/PDSCH/PUCCH] UE %d RNTI %04x DCI L %d start %3d RBs %3d startSymbol %2d nb_symbol %2d dmrspos %x MCS %2d nrOfLayers %d TBS %4d HARQ PID %2d round %d RV %d NDI %d dl_data_to_ULACK %d (%d.%d) PUCCH allocation %d TPC %d\n",
|
||||
frame,
|
||||
slot,
|
||||
UE_id,
|
||||
@@ -1156,8 +1175,8 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
pucch->ul_slot,
|
||||
sched_pdsch->pucch_allocation,
|
||||
sched_ctrl->tpc1);
|
||||
|
||||
NR_BWP_Downlink_t *bwp = sched_ctrl->active_bwp;
|
||||
|
||||
const NR_SIB1_t *sib1 = RC.nrmac[module_id]->common_channels[0].sib1 ? RC.nrmac[module_id]->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL;
|
||||
NR_BWP_t *genericParameters = get_dl_bwp_genericParameters(bwp,
|
||||
RC.nrmac[module_id]->common_channels[0].ServingCellConfigCommon,
|
||||
@@ -1170,6 +1189,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
|
||||
/* look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not exist, create it */
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = gNB_mac->pdcch_pdu_idx[CC_id][coresetid];
|
||||
|
||||
if (!pdcch_pdu) {
|
||||
LOG_D(NR_MAC, "creating pdcch pdu, pdcch_pdu = NULL. \n");
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
|
||||
@@ -1190,7 +1210,6 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu));
|
||||
dl_req->nPDUs += 1;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
|
||||
|
||||
pdsch_pdu->pduBitmap = 0;
|
||||
pdsch_pdu->rnti = rnti;
|
||||
/* SCF222: PDU index incremented for each PDSCH PDU sent in TX control
|
||||
@@ -1208,9 +1227,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
}
|
||||
|
||||
pdsch_pdu->SubcarrierSpacing = genericParameters->subcarrierSpacing;
|
||||
|
||||
pdsch_pdu->CyclicPrefix = genericParameters->cyclicPrefix ? *genericParameters->cyclicPrefix : 0;
|
||||
|
||||
// Codeword information
|
||||
pdsch_pdu->NrOfCodewords = 1;
|
||||
pdsch_pdu->targetCodeRate[0] = R;
|
||||
@@ -1221,12 +1238,10 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
AssertFatal(harq->round<4,"%d",harq->round);
|
||||
pdsch_pdu->rvIndex[0] = nr_rv_round_map[harq->round];
|
||||
pdsch_pdu->TBSize[0] = TBS;
|
||||
|
||||
pdsch_pdu->dataScramblingId = *scc->physCellId;
|
||||
pdsch_pdu->nrOfLayers = nrOfLayers;
|
||||
pdsch_pdu->transmissionScheme = 0;
|
||||
pdsch_pdu->refPoint = 0; // Point A
|
||||
|
||||
// DMRS
|
||||
pdsch_pdu->dlDmrsSymbPos = ps->dl_dmrs_symb_pos;
|
||||
pdsch_pdu->dmrsConfigType = ps->dmrsConfigType;
|
||||
@@ -1234,18 +1249,16 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
pdsch_pdu->SCID = 0;
|
||||
pdsch_pdu->numDmrsCdmGrpsNoData = ps->numDmrsCdmGrpsNoData;
|
||||
pdsch_pdu->dmrsPorts = (1<<nrOfLayers)-1; // FIXME with a better implementation
|
||||
|
||||
// Pdsch Allocation in frequency domain
|
||||
pdsch_pdu->resourceAlloc = 1;
|
||||
pdsch_pdu->rbStart = sched_pdsch->rbStart;
|
||||
pdsch_pdu->rbSize = sched_pdsch->rbSize;
|
||||
pdsch_pdu->VRBtoPRBMapping = 1; // non-interleaved, check if this is ok for initialBWP
|
||||
|
||||
// Resource Allocation in time domain
|
||||
pdsch_pdu->StartSymbolIndex = ps->startSymbolIndex;
|
||||
pdsch_pdu->NrOfSymbols = ps->nrOfSymbols;
|
||||
|
||||
NR_PDSCH_Config_t *pdsch_Config=NULL;
|
||||
|
||||
if (bwp &&
|
||||
bwp->bwp_Dedicated &&
|
||||
bwp->bwp_Dedicated->pdsch_Config &&
|
||||
@@ -1254,18 +1267,20 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
|
||||
/* Check and validate PTRS values */
|
||||
struct NR_SetupRelease_PTRS_DownlinkConfig *phaseTrackingRS =
|
||||
pdsch_Config ? pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS : NULL;
|
||||
pdsch_Config ? pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS : NULL;
|
||||
|
||||
if (phaseTrackingRS) {
|
||||
bool valid_ptrs_setup = set_dl_ptrs_values(phaseTrackingRS->choice.setup,
|
||||
pdsch_pdu->rbSize,
|
||||
pdsch_pdu->mcsIndex[0],
|
||||
pdsch_pdu->mcsTable[0],
|
||||
&pdsch_pdu->PTRSFreqDensity,
|
||||
&pdsch_pdu->PTRSTimeDensity,
|
||||
&pdsch_pdu->PTRSPortIndex,
|
||||
&pdsch_pdu->nEpreRatioOfPDSCHToPTRS,
|
||||
&pdsch_pdu->PTRSReOffset,
|
||||
pdsch_pdu->NrOfSymbols);
|
||||
pdsch_pdu->rbSize,
|
||||
pdsch_pdu->mcsIndex[0],
|
||||
pdsch_pdu->mcsTable[0],
|
||||
&pdsch_pdu->PTRSFreqDensity,
|
||||
&pdsch_pdu->PTRSTimeDensity,
|
||||
&pdsch_pdu->PTRSPortIndex,
|
||||
&pdsch_pdu->nEpreRatioOfPDSCHToPTRS,
|
||||
&pdsch_pdu->PTRSReOffset,
|
||||
pdsch_pdu->NrOfSymbols);
|
||||
|
||||
if (valid_ptrs_setup)
|
||||
pdsch_pdu->pduBitmap |= 0x1; // Bit 0: pdschPtrs - Indicates PTRS included (FR2)
|
||||
}
|
||||
@@ -1275,6 +1290,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu->dci_pdu[pdcch_pdu->numDlDci];
|
||||
pdcch_pdu->numDlDci++;
|
||||
dci_pdu->RNTI = rnti;
|
||||
|
||||
if (sched_ctrl->coreset &&
|
||||
sched_ctrl->search_space &&
|
||||
sched_ctrl->coreset->pdcch_DMRS_ScramblingID &&
|
||||
@@ -1285,27 +1301,28 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
dci_pdu->ScramblingId = *scc->physCellId;
|
||||
dci_pdu->ScramblingRNTI = 0;
|
||||
}
|
||||
|
||||
dci_pdu->AggregationLevel = sched_ctrl->aggregation_level;
|
||||
dci_pdu->CceIndex = sched_ctrl->cce_index;
|
||||
dci_pdu->beta_PDCCH_1_0 = 0;
|
||||
dci_pdu->powerControlOffsetSS = 1;
|
||||
|
||||
/* DCI payload */
|
||||
dci_pdu_rel15_t dci_payload;
|
||||
memset(&dci_payload, 0, sizeof(dci_pdu_rel15_t));
|
||||
// bwp indicator
|
||||
const int n_dl_bwp = bwp ? UE_info->CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count : 0;
|
||||
AssertFatal(n_dl_bwp <= 1, "downlinkBWP_ToAddModList has %d BWP!\n", n_dl_bwp);
|
||||
|
||||
// as per table 7.3.1.1.2-1 in 38.212
|
||||
dci_payload.bwp_indicator.val = bwp ? (n_dl_bwp < 4 ? bwp->bwp_Id : bwp->bwp_Id - 1) : 0;
|
||||
|
||||
if (bwp) AssertFatal(bwp->bwp_Dedicated->pdsch_Config->choice.setup->resourceAllocation == NR_PDSCH_Config__resourceAllocation_resourceAllocationType1,
|
||||
"Only frequency resource allocation type 1 is currently supported\n");
|
||||
"Only frequency resource allocation type 1 is currently supported\n");
|
||||
|
||||
dci_payload.frequency_domain_assignment.val =
|
||||
PRBalloc_to_locationandbandwidth0(
|
||||
pdsch_pdu->rbSize,
|
||||
pdsch_pdu->rbStart,
|
||||
pdsch_pdu->BWPSize);
|
||||
PRBalloc_to_locationandbandwidth0(
|
||||
pdsch_pdu->rbSize,
|
||||
pdsch_pdu->rbStart,
|
||||
pdsch_pdu->BWPSize);
|
||||
dci_payload.format_indicator = 1;
|
||||
dci_payload.time_domain_assignment.val = ps->time_domain_allocation;
|
||||
dci_payload.mcs = sched_pdsch->mcs;
|
||||
@@ -1336,11 +1353,11 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
dci_payload.tpc,
|
||||
pucch->timing_indicator);
|
||||
|
||||
|
||||
int dci_format = ss && ss->searchSpaceType && ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific ?
|
||||
NR_DL_DCI_FORMAT_1_1 : NR_DL_DCI_FORMAT_1_0;
|
||||
|
||||
const int rnti_type = NR_RNTI_C;
|
||||
|
||||
fill_dci_pdu_rel15(scc,
|
||||
UE_info->CellGroup[UE_id],
|
||||
dci_pdu,
|
||||
@@ -1359,7 +1376,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
|
||||
if (harq->round != 0) { /* retransmission */
|
||||
/* we do not have to do anything, since we do not require to get data
|
||||
* from RLC or encode MAC CEs. The TX_req structure is filled below
|
||||
* from RLC or encode MAC CEs. The TX_req structure is filled below
|
||||
* or copy data to FAPI structures */
|
||||
LOG_D(NR_MAC,
|
||||
"%d.%2d DL retransmission UE %d/RNTI %04x HARQ PID %d round %d NDI %d\n",
|
||||
@@ -1370,20 +1387,15 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
current_harq_pid,
|
||||
harq->round,
|
||||
harq->ndi);
|
||||
|
||||
AssertFatal(harq->sched_pdsch.tb_size == TBS,
|
||||
"UE %d mismatch between scheduled TBS and buffered TB for HARQ PID %d\n",
|
||||
UE_id,
|
||||
current_harq_pid);
|
||||
|
||||
T(T_GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti),
|
||||
T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_INT(harq->round), T_BUFFER(harq->tb, TBS));
|
||||
T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_INT(harq->round), T_BUFFER(harq->transportBlock, TBS));
|
||||
} else { /* initial transmission */
|
||||
|
||||
LOG_D(NR_MAC, "[%s] Initial HARQ transmission in %d.%d\n", __FUNCTION__, frame, slot);
|
||||
|
||||
uint8_t *buf = (uint8_t *) harq->tb;
|
||||
|
||||
uint8_t *buf = (uint8_t *) harq->transportBlock;
|
||||
/* first, write all CEs that might be there */
|
||||
int written = nr_write_ce_dlsch_pdu(module_id,
|
||||
sched_ctrl,
|
||||
@@ -1391,32 +1403,30 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
255, // no drx
|
||||
NULL); // contention res id
|
||||
buf += written;
|
||||
int size = TBS - written;
|
||||
DevAssert(size >= 0);
|
||||
uint8_t *bufEnd = buf + TBS - written;
|
||||
DevAssert(TBS > written);
|
||||
int dlsch_total_bytes = 0;
|
||||
/* next, get RLC data */
|
||||
|
||||
start_meas(&gNB_mac->rlc_data_req);
|
||||
if (sched_ctrl->num_total_bytes > 0) {
|
||||
|
||||
if (sched_ctrl->num_total_bytes > 0) {
|
||||
/* loop over all activated logical channels */
|
||||
for (int i = 0; i < sched_ctrl->dl_lc_num; ++i) {
|
||||
|
||||
const int lcid = sched_ctrl->dl_lc_ids[i];
|
||||
if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0)
|
||||
continue; // no data for this LC
|
||||
|
||||
int dlsch_total_bytes = 0;
|
||||
while (size > 3) {
|
||||
if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0)
|
||||
continue; // no data for this LC tbs_size_t len = 0;
|
||||
|
||||
int lcid_bytes=0;
|
||||
while (bufEnd-buf > sizeof(NR_MAC_SUBHEADER_LONG) + 1 ) {
|
||||
// we do not know how much data we will get from RLC, i.e., whether it
|
||||
// will be longer than 256B or not. Therefore, reserve space for long header, then
|
||||
// fetch data, then fill real length
|
||||
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf;
|
||||
buf += 3;
|
||||
size -= 3;
|
||||
|
||||
/* limit requested number of bytes to what preprocessor specified, or
|
||||
* such that TBS is full */
|
||||
const rlc_buffer_occupancy_t ndata = min(sched_ctrl->rlc_status[lcid].bytes_in_buffer, size);
|
||||
const rlc_buffer_occupancy_t ndata = min(sched_ctrl->rlc_status[lcid].bytes_in_buffer,
|
||||
bufEnd-buf-sizeof(NR_MAC_SUBHEADER_LONG));
|
||||
tbs_size_t len = mac_rlc_data_req(module_id,
|
||||
rnti,
|
||||
module_id,
|
||||
@@ -1425,12 +1435,11 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
MBMS_FLAG_NO,
|
||||
lcid,
|
||||
ndata,
|
||||
(char *)buf,
|
||||
(char *)buf+sizeof(NR_MAC_SUBHEADER_LONG),
|
||||
0,
|
||||
0);
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"%4d.%2d RNTI %04x: %d bytes from %s %d (ndata %d, remaining size %d)\n",
|
||||
"%4d.%2d RNTI %04x: %d bytes from %s %d (ndata %d, remaining size %ld)\n",
|
||||
frame,
|
||||
slot,
|
||||
rnti,
|
||||
@@ -1438,64 +1447,56 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
lcid < 4 ? "DCCH" : "DTCH",
|
||||
lcid,
|
||||
ndata,
|
||||
size);
|
||||
if (len == 0) {
|
||||
/* RLC did not have data anymore, mark buffer as unused */
|
||||
buf -= 3;
|
||||
size += 3;
|
||||
bufEnd-buf-+sizeof(NR_MAC_SUBHEADER_LONG));
|
||||
|
||||
if (len == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
header->R = 0;
|
||||
header->F = 1;
|
||||
header->LCID = lcid;
|
||||
header->L1 = (len >> 8) & 0xff;
|
||||
header->L2 = len & 0xff;
|
||||
size -= len;
|
||||
buf += len;
|
||||
header->L = htons(len);
|
||||
buf += len+sizeof(NR_MAC_SUBHEADER_LONG);
|
||||
dlsch_total_bytes += len;
|
||||
lcid_bytes += len;
|
||||
}
|
||||
|
||||
UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += dlsch_total_bytes;
|
||||
UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += lcid_bytes;
|
||||
}
|
||||
} else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra) {
|
||||
/* we will need the large header, phy-test typically allocates all
|
||||
* resources and fills to the last byte below */
|
||||
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf;
|
||||
buf += 3;
|
||||
size -= 3;
|
||||
DevAssert(size > 0);
|
||||
LOG_D(NR_MAC, "Configuring DL_TX in %d.%d: TBS %d with %d B of random data\n", frame, slot, TBS, size);
|
||||
// fill dlsch_buffer with random data
|
||||
for (int i = 0; i < size; i++)
|
||||
buf[i] = lrand48() & 0xff;
|
||||
header->R = 0;
|
||||
header->F = 1;
|
||||
header->LCID = DL_SCH_LCID_PADDING;
|
||||
header->L1 = (size >> 8) & 0xff;
|
||||
header->L2 = size & 0xff;
|
||||
size -= size;
|
||||
buf += size;
|
||||
LOG_D(NR_MAC, "Configuring DL_TX in %d.%d: TBS %d of random data\n", frame, slot, TBS);
|
||||
|
||||
if (bufEnd-buf > sizeof(NR_MAC_SUBHEADER_LONG) ) {
|
||||
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf;
|
||||
// fill dlsch_buffer with random data
|
||||
header->R = 0;
|
||||
header->F = 1;
|
||||
header->LCID = DL_SCH_LCID_PADDING;
|
||||
buf += sizeof(NR_MAC_SUBHEADER_LONG);
|
||||
header->L = htons(bufEnd-buf);
|
||||
dlsch_total_bytes += bufEnd-buf;
|
||||
|
||||
for (; buf < bufEnd; buf++)
|
||||
*buf = lrand48() & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
stop_meas(&gNB_mac->rlc_data_req);
|
||||
|
||||
// Add padding header and zero rest out if there is space left
|
||||
if (size > 0) {
|
||||
if (bufEnd-buf > 0) {
|
||||
NR_MAC_SUBHEADER_FIXED *padding = (NR_MAC_SUBHEADER_FIXED *) buf;
|
||||
padding->R = 0;
|
||||
padding->LCID = DL_SCH_LCID_PADDING;
|
||||
size -= 1;
|
||||
buf += 1;
|
||||
while (size > 0) {
|
||||
*buf = 0;
|
||||
buf += 1;
|
||||
size -= 1;
|
||||
}
|
||||
memset(buf,0,bufEnd-buf);
|
||||
buf=bufEnd;
|
||||
}
|
||||
|
||||
UE_info->mac_stats[UE_id].dlsch_total_bytes += TBS;
|
||||
UE_info->mac_stats[UE_id].dlsch_current_bytes = TBS;
|
||||
|
||||
/* save retransmission information */
|
||||
harq->sched_pdsch = *sched_pdsch;
|
||||
/* save which time allocation has been used, to be used on
|
||||
@@ -1514,7 +1515,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
}
|
||||
|
||||
T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti),
|
||||
T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(harq->tb, TBS));
|
||||
T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock, TBS));
|
||||
}
|
||||
|
||||
const int ntx_req = gNB_mac->TX_req[CC_id].Number_of_PDUs;
|
||||
@@ -1523,11 +1524,10 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
tx_req->PDU_index = pduindex;
|
||||
tx_req->num_TLV = 1;
|
||||
tx_req->TLVs[0].length = TBS + 2;
|
||||
memcpy(tx_req->TLVs[0].value.direct, harq->tb, TBS);
|
||||
memcpy(tx_req->TLVs[0].value.direct, harq->transportBlock, TBS);
|
||||
gNB_mac->TX_req[CC_id].Number_of_PDUs++;
|
||||
gNB_mac->TX_req[CC_id].SFN = frame;
|
||||
gNB_mac->TX_req[CC_id].Slot = slot;
|
||||
|
||||
/* mark UE as scheduled */
|
||||
sched_pdsch->rbSize = 0;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ void nr_fill_nfapi_pucch(module_id_t mod_id,
|
||||
&RC.nrmac[mod_id]->UL_tti_req_ahead[0][pucch->ul_slot];
|
||||
AssertFatal(future_ul_tti_req->SFN == pucch->frame
|
||||
&& future_ul_tti_req->Slot == pucch->ul_slot,
|
||||
"future UL_tti_req's frame.slot %d.%d does not match PUCCH %d.%d\n",
|
||||
"future UL_tti_req's frame.slot %4d.%2d does not match PUCCH %4d.%2d\n",
|
||||
future_ul_tti_req->SFN,
|
||||
future_ul_tti_req->Slot,
|
||||
pucch->frame,
|
||||
@@ -84,7 +84,7 @@ void nr_fill_nfapi_pucch(module_id_t mod_id,
|
||||
cg->spCellConfig->spCellConfigDedicated->uplinkConfig ?
|
||||
cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP : NULL;
|
||||
|
||||
LOG_D(NR_MAC,"%d.%d Calling nr_configure_pucch (ubwpd %p,r_pucch %d) pucch to be scheduled in %d.%d\n",
|
||||
LOG_D(NR_MAC,"%4d.%2d Calling nr_configure_pucch (ubwpd %p,r_pucch %d) pucch to be scheduled in %4d.%2d\n",
|
||||
frame,slot,ubwpd,pucch->r_pucch,pucch->frame,pucch->ul_slot);
|
||||
|
||||
const NR_SIB1_t *sib1 = nr_mac->common_channels[0].sib1 ? nr_mac->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL;
|
||||
@@ -161,7 +161,7 @@ void nr_schedule_pucch(int Mod_idP,
|
||||
|| frameP != curr_pucch->frame
|
||||
|| slotP != curr_pucch->ul_slot)
|
||||
continue;
|
||||
LOG_D(NR_MAC,"Scheduling PUCCH[%d] RX for UE %d in %d.%d O_ack %d\n",i,UE_id,curr_pucch->frame,curr_pucch->ul_slot,O_ack);
|
||||
LOG_D(NR_MAC,"Scheduling PUCCH[%d] RX for UE %d in %4d.%2d O_ack %d\n",i,UE_id,curr_pucch->frame,curr_pucch->ul_slot,O_ack);
|
||||
nr_fill_nfapi_pucch(Mod_idP, frameP, slotP, curr_pucch, UE_id);
|
||||
memset(curr_pucch, 0, sizeof(*curr_pucch));
|
||||
}
|
||||
@@ -820,6 +820,7 @@ static void handle_dl_harq(module_id_t mod_id,
|
||||
stats->dlsch_errors++;
|
||||
LOG_D(NR_MAC, "retransmission error for UE %d (total %"PRIu64")\n", UE_id, stats->dlsch_errors);
|
||||
} else {
|
||||
LOG_D(PHY,"NACK for: pid %d, ue %x\n",harq_pid, UE_id);
|
||||
add_tail_nr_list(&UE_info->UE_sched_ctrl[UE_id].retrans_dl_harq, harq_pid);
|
||||
harq->round++;
|
||||
}
|
||||
@@ -1398,7 +1399,7 @@ static NR_UE_harq_t *find_harq(module_id_t mod_id, frame_t frame, sub_frame_t sl
|
||||
while (harq->feedback_frame != frame
|
||||
|| (harq->feedback_frame == frame && harq->feedback_slot < slot)) {
|
||||
LOG_W(NR_MAC,
|
||||
"expected HARQ pid %d feedback at %d.%d, but is at %d.%d instead (HARQ feedback is in the past)\n",
|
||||
"expected HARQ pid %d feedback at %4d.%2d, but is at %4d.%2d instead (HARQ feedback is in the past)\n",
|
||||
pid,
|
||||
harq->feedback_frame,
|
||||
harq->feedback_slot,
|
||||
@@ -1414,7 +1415,7 @@ static NR_UE_harq_t *find_harq(module_id_t mod_id, frame_t frame, sub_frame_t sl
|
||||
/* feedbacks that we wait for in the future: don't do anything */
|
||||
if (harq->feedback_slot > slot) {
|
||||
LOG_W(NR_MAC,
|
||||
"expected HARQ pid %d feedback at %d.%d, but is at %d.%d instead (HARQ feedback is in the future)\n",
|
||||
"expected HARQ pid %d feedback at %4d.%2d, but is at %4d.%2d instead (HARQ feedback is in the future)\n",
|
||||
pid,
|
||||
harq->feedback_frame,
|
||||
harq->feedback_slot,
|
||||
@@ -1451,7 +1452,7 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id,
|
||||
DevAssert(harq->is_waiting);
|
||||
const int8_t pid = sched_ctrl->feedback_dl_harq.head;
|
||||
remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
|
||||
LOG_D(NR_MAC,"bit %d pid %d ack/nack %d\n",harq_bit,pid,harq_value);
|
||||
LOG_D(NR_MAC,"%4d.%2d bit %d pid %d ack/nack %d\n",frame, slot, harq_bit,pid,harq_value);
|
||||
handle_dl_harq(mod_id, UE_id, pid, harq_value == 0 && harq_confidence == 0);
|
||||
if (harq_confidence == 1) UE_info->mac_stats[UE_id].pucch0_DTX++;
|
||||
}
|
||||
@@ -1635,7 +1636,7 @@ int nr_acknack_scheduling(int mod_id,
|
||||
int bwp_size = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
|
||||
|
||||
NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[0];
|
||||
LOG_D(NR_MAC, "In %s: %d.%d Trying to allocate pucch, current DAI %d\n", __FUNCTION__, frame, slot, pucch->dai_c);
|
||||
LOG_D(NR_MAC, "In %s: %4d.%2d Trying to allocate pucch, current DAI %d\n", __FUNCTION__, frame, slot, pucch->dai_c);
|
||||
|
||||
pucch->r_pucch=r_pucch;
|
||||
AssertFatal(pucch->csi_bits == 0,
|
||||
@@ -1649,7 +1650,7 @@ int nr_acknack_scheduling(int mod_id,
|
||||
* the same slot again */
|
||||
const int f = pucch->frame;
|
||||
const int s = pucch->ul_slot;
|
||||
LOG_D(NR_MAC, "In %s: %d.%d DAI = 2 pucch currently in %d.%d, advancing by 1 slot\n", __FUNCTION__, frame, slot, f, s);
|
||||
LOG_D(NR_MAC, "In %s: %4d.%2d DAI = 2 pucch currently in %4d.%2d, advancing by 1 slot\n", __FUNCTION__, frame, slot, f, s);
|
||||
nr_fill_nfapi_pucch(mod_id, frame, slot, pucch, UE_id);
|
||||
memset(pucch, 0, sizeof(*pucch));
|
||||
pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f;
|
||||
@@ -1676,7 +1677,7 @@ int nr_acknack_scheduling(int mod_id,
|
||||
}
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC, "In %s: pucch_acknak 1. DL %d.%d, UL_ACK %d.%d, DAI_C %d\n", __FUNCTION__, frame, slot, pucch->frame, pucch->ul_slot, pucch->dai_c);
|
||||
LOG_D(NR_MAC, "In %s: pucch_acknak 1. DL %4d.%2d, UL_ACK %4d.%2d, DAI_C %d\n", __FUNCTION__, frame, slot, pucch->frame, pucch->ul_slot, pucch->dai_c);
|
||||
|
||||
// this is hardcoded for now as ue specific only if we are not on the initialBWP (to be fixed to allow ue_Specific also on initialBWP
|
||||
NR_BWP_UplinkDedicated_t *ubwpd=NULL;
|
||||
@@ -1696,7 +1697,7 @@ int nr_acknack_scheduling(int mod_id,
|
||||
int max_fb_time = 0;
|
||||
get_pdsch_to_harq_feedback(mod_id, UE_id, bwp_Id, ss_type, &max_fb_time, pdsch_to_harq_feedback);
|
||||
|
||||
LOG_D(NR_MAC, "In %s: 1b. DL %d.%d, UL_ACK %d.%d, DAI_C %d\n", __FUNCTION__, frame,slot,pucch->frame,pucch->ul_slot,pucch->dai_c);
|
||||
LOG_D(NR_MAC, "In %s: 1b. DL %4d.%2d, UL_ACK %4d.%2d, DAI_C %d\n", __FUNCTION__, frame,slot,pucch->frame,pucch->ul_slot,pucch->dai_c);
|
||||
/* there is a HARQ. Check whether we can use it for this ACKNACK */
|
||||
if (pucch->dai_c > 0) {
|
||||
/* this UE already has a PUCCH occasion */
|
||||
@@ -1716,7 +1717,7 @@ int nr_acknack_scheduling(int mod_id,
|
||||
const int f = pucch->frame;
|
||||
const int s = pucch->ul_slot;
|
||||
const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||
LOG_D(NR_MAC, "In %s: %d.%d DAI > 0, cannot reach timing for pucch in %d.%d, advancing slot by 1 and trying again\n", __FUNCTION__, frame, slot, f, s);
|
||||
LOG_D(NR_MAC, "In %s: %4d.%2d DAI > 0, cannot reach timing for pucch in %4d.%2d, advancing slot by 1 and trying again\n", __FUNCTION__, frame, slot, f, s);
|
||||
nr_fill_nfapi_pucch(mod_id, frame, slot, pucch, UE_id);
|
||||
memset(pucch, 0, sizeof(*pucch));
|
||||
pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f;
|
||||
@@ -1730,11 +1731,11 @@ int nr_acknack_scheduling(int mod_id,
|
||||
pucch->timing_indicator = i;
|
||||
pucch->dai_c++;
|
||||
// retain old resource indicator, and we are good
|
||||
LOG_D(NR_MAC, "In %s: %d.%d. DAI > 0, pucch allocated for %d.%d (index %d)\n", __FUNCTION__, frame,slot,pucch->frame,pucch->ul_slot,pucch->timing_indicator);
|
||||
LOG_D(NR_MAC, "In %s: %4d.%2d. DAI > 0, pucch allocated for %4d.%2d (index %d)\n", __FUNCTION__, frame,slot,pucch->frame,pucch->ul_slot,pucch->timing_indicator);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC, "In %s: %d.%d DAI = 0, looking for new pucch occasion\n", __FUNCTION__, frame, slot);
|
||||
LOG_D(NR_MAC, "In %s: %4d.%2d DAI = 0, looking for new pucch occasion\n", __FUNCTION__, frame, slot);
|
||||
/* we need to find a new PUCCH occasion */
|
||||
|
||||
/*(Re)Inizialization of timing information*/
|
||||
@@ -1837,7 +1838,7 @@ int nr_acknack_scheduling(int mod_id,
|
||||
|
||||
pucch->timing_indicator = ind_found; // index in the list of timing indicators
|
||||
|
||||
LOG_D(NR_MAC, "In %s: 2. DAI 0 DL %d.%d, UL_ACK %d.%d (index %d)\n", __FUNCTION__, frame,slot,pucch->frame,pucch->ul_slot,pucch->timing_indicator);
|
||||
LOG_D(NR_MAC, "In %s: 2. DAI 0 DL %4d.%2d, UL_ACK %4d.%2d (index %d)\n", __FUNCTION__, frame,slot,pucch->frame,pucch->ul_slot,pucch->timing_indicator);
|
||||
|
||||
pucch->dai_c++;
|
||||
pucch->resource_indicator = 0; // each UE has dedicated PUCCH resources
|
||||
|
||||
@@ -213,11 +213,8 @@ int nr_process_mac_pdu(module_id_t module_idP,
|
||||
int pdu_len)
|
||||
{
|
||||
|
||||
uint8_t rx_lcid;
|
||||
|
||||
uint8_t done = 0;
|
||||
uint16_t mac_ce_len;
|
||||
uint16_t mac_subheader_len;
|
||||
uint16_t mac_sdu_len;
|
||||
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[module_idP]->UE_info;
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
@@ -231,10 +228,9 @@ int nr_process_mac_pdu(module_id_t module_idP,
|
||||
#endif
|
||||
|
||||
while (!done && pdu_len > 0){
|
||||
mac_ce_len = 0;
|
||||
mac_subheader_len = sizeof(NR_MAC_SUBHEADER_FIXED);
|
||||
mac_sdu_len = 0;
|
||||
rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID;
|
||||
uint16_t mac_len=0;
|
||||
uint16_t mac_subheader_len=sizeof(NR_MAC_SUBHEADER_FIXED);
|
||||
uint8_t rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID;
|
||||
|
||||
LOG_D(NR_MAC, "In %s: received UL-SCH sub-PDU with LCID 0x%x in %d.%d (remaining PDU length %d)\n", __func__, rx_lcid, frameP, slot, pdu_len);
|
||||
|
||||
@@ -249,7 +245,7 @@ int nr_process_mac_pdu(module_id_t module_idP,
|
||||
#endif*/
|
||||
case UL_SCH_LCID_RECOMMENDED_BITRATE_QUERY:
|
||||
// 38.321 Ch6.1.3.20
|
||||
mac_ce_len = 2;
|
||||
mac_len = 2;
|
||||
break;
|
||||
case UL_SCH_LCID_CONFIGURED_GRANT_CONFIRMATION:
|
||||
// 38.321 Ch6.1.3.7
|
||||
@@ -259,7 +255,7 @@ int nr_process_mac_pdu(module_id_t module_idP,
|
||||
case UL_SCH_LCID_S_TRUNCATED_BSR:
|
||||
//38.321 section 6.1.3.1
|
||||
//fixed length
|
||||
mac_ce_len =1;
|
||||
mac_len =1;
|
||||
/* Extract short BSR value */
|
||||
ce_ptr = &pduP[mac_subheader_len];
|
||||
NR_BSR_SHORT *bsr_s = (NR_BSR_SHORT *) ce_ptr;
|
||||
@@ -284,16 +280,8 @@ int nr_process_mac_pdu(module_id_t module_idP,
|
||||
to be a partial PDU at the end of this buffer, so here
|
||||
we gracefully ignore that by returning 0. See:
|
||||
https://gitlab.eurecom.fr/oai/openairinterface5g/-/issues/534 */
|
||||
if (pdu_len < sizeof(NR_MAC_SUBHEADER_SHORT))
|
||||
return 0;
|
||||
mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L;
|
||||
mac_subheader_len = 2;
|
||||
if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){
|
||||
if (pdu_len < sizeof(NR_MAC_SUBHEADER_LONG))
|
||||
return 0;
|
||||
mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8;
|
||||
mac_subheader_len = 3;
|
||||
}
|
||||
if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len))
|
||||
return 0;
|
||||
/* Extract long BSR value */
|
||||
ce_ptr = &pduP[mac_subheader_len];
|
||||
NR_BSR_LONG *bsr_l = (NR_BSR_LONG *) ce_ptr;
|
||||
@@ -339,14 +327,14 @@ int nr_process_mac_pdu(module_id_t module_idP,
|
||||
|
||||
//38.321 section 6.1.3.2
|
||||
//fixed length
|
||||
mac_ce_len = 2;
|
||||
mac_len = 2;
|
||||
/* Extract CRNTI value */
|
||||
break;
|
||||
|
||||
case UL_SCH_LCID_SINGLE_ENTRY_PHR:
|
||||
//38.321 section 6.1.3.8
|
||||
//fixed length
|
||||
mac_ce_len = 2;
|
||||
mac_len = 2;
|
||||
/* Extract SINGLE ENTRY PHR elements for PHR calculation */
|
||||
ce_ptr = &pduP[mac_subheader_len];
|
||||
NR_SINGLE_ENTRY_PHR_MAC_CE *phr = (NR_SINGLE_ENTRY_PHR_MAC_CE *) ce_ptr;
|
||||
@@ -367,32 +355,16 @@ int nr_process_mac_pdu(module_id_t module_idP,
|
||||
case UL_SCH_LCID_MULTI_ENTRY_PHR_1_OCT:
|
||||
//38.321 section 6.1.3.9
|
||||
// varialbe length
|
||||
if (pdu_len < sizeof(NR_MAC_SUBHEADER_SHORT))
|
||||
return 0;
|
||||
mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L;
|
||||
mac_subheader_len = 2;
|
||||
if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){
|
||||
if (pdu_len < sizeof(NR_MAC_SUBHEADER_LONG))
|
||||
return 0;
|
||||
mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8;
|
||||
mac_subheader_len = 3;
|
||||
}
|
||||
if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len))
|
||||
return 0;
|
||||
/* Extract MULTI ENTRY PHR elements from single octet bitmap for PHR calculation */
|
||||
break;
|
||||
|
||||
case UL_SCH_LCID_MULTI_ENTRY_PHR_4_OCT:
|
||||
//38.321 section 6.1.3.9
|
||||
// varialbe length
|
||||
if (pdu_len < sizeof(NR_MAC_SUBHEADER_SHORT))
|
||||
return 0;
|
||||
mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L;
|
||||
mac_subheader_len = 2;
|
||||
if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){
|
||||
if (pdu_len < sizeof(NR_MAC_SUBHEADER_LONG))
|
||||
return 0;
|
||||
mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8;
|
||||
mac_subheader_len = 3;
|
||||
}
|
||||
if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len))
|
||||
return 0;
|
||||
/* Extract MULTI ENTRY PHR elements from four octets bitmap for PHR calculation */
|
||||
break;
|
||||
|
||||
@@ -403,27 +375,16 @@ int nr_process_mac_pdu(module_id_t module_idP,
|
||||
|
||||
case UL_SCH_LCID_SRB1:
|
||||
case UL_SCH_LCID_SRB2:
|
||||
if (pdu_len < sizeof(NR_MAC_SUBHEADER_SHORT))
|
||||
return 0;
|
||||
if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){
|
||||
//mac_sdu_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8;
|
||||
if (pdu_len < sizeof(NR_MAC_SUBHEADER_LONG))
|
||||
return 0;
|
||||
mac_subheader_len = 3;
|
||||
mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *) pduP)->L1 & 0x7f) << 8)
|
||||
| ((uint16_t)((NR_MAC_SUBHEADER_LONG *) pduP)->L2 & 0xff);
|
||||
} else {
|
||||
mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L;
|
||||
mac_subheader_len = 2;
|
||||
}
|
||||
if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len))
|
||||
return 0;
|
||||
|
||||
rnti_t crnti = UE_info->rnti[UE_id];
|
||||
int UE_idx = UE_id;
|
||||
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
|
||||
NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i];
|
||||
if (ra->state >= WAIT_Msg3 && ra->rnti == UE_info->rnti[UE_id]) {
|
||||
uint8_t *next_subpduP = pduP + mac_subheader_len + mac_sdu_len;
|
||||
if ((pduP[mac_subheader_len+mac_sdu_len] & 0x3F) == UL_SCH_LCID_C_RNTI) {
|
||||
uint8_t *next_subpduP = pduP + mac_subheader_len + mac_len;
|
||||
if ((pduP[mac_subheader_len+mac_len] & 0x3F) == UL_SCH_LCID_C_RNTI) {
|
||||
crnti = ((next_subpduP[1]&0xFF)<<8)|(next_subpduP[2]&0xFF);
|
||||
UE_idx = find_nr_UE_id(module_idP, crnti);
|
||||
break;
|
||||
@@ -432,7 +393,7 @@ int nr_process_mac_pdu(module_id_t module_idP,
|
||||
}
|
||||
|
||||
if (UE_info->CellGroup[UE_idx]) {
|
||||
LOG_D(NR_MAC, "[UE %d] Frame %d : ULSCH -> UL-DCCH %d (gNB %d, %d bytes), rnti: 0x%04x \n", module_idP, frameP, rx_lcid, module_idP, mac_sdu_len, crnti);
|
||||
LOG_D(NR_MAC, "[UE %d] Frame %d : ULSCH -> UL-DCCH %d (gNB %d, %d bytes), rnti: 0x%04x \n", module_idP, frameP, rx_lcid, module_idP, mac_len, crnti);
|
||||
mac_rlc_data_ind(module_idP,
|
||||
crnti,
|
||||
module_idP,
|
||||
@@ -441,7 +402,7 @@ int nr_process_mac_pdu(module_id_t module_idP,
|
||||
MBMS_FLAG_NO,
|
||||
rx_lcid,
|
||||
(char *) (pduP + mac_subheader_len),
|
||||
mac_sdu_len,
|
||||
mac_len,
|
||||
1,
|
||||
NULL);
|
||||
} else {
|
||||
@@ -459,23 +420,23 @@ int nr_process_mac_pdu(module_id_t module_idP,
|
||||
|
||||
if ( rx_lcid == UL_SCH_LCID_CCCH1 ) {
|
||||
// RRCResumeRequest1 message includes the full I-RNTI and has a size of 8 bytes
|
||||
mac_sdu_len = 8;
|
||||
mac_len = 8;
|
||||
|
||||
// Check if it is a valid CCCH1 message, we get all 00's messages very often
|
||||
int i = 0;
|
||||
for(i=0; i<(mac_subheader_len+mac_sdu_len); i++) {
|
||||
for(i=0; i<(mac_subheader_len+mac_len); i++) {
|
||||
if(pduP[i] != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == (mac_subheader_len+mac_sdu_len)) {
|
||||
if (i == (mac_subheader_len+mac_len)) {
|
||||
LOG_D(NR_MAC, "%s() Invalid CCCH1 message!, pdu_len: %d\n", __func__, pdu_len);
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// fixed length of 6 bytes
|
||||
mac_sdu_len = 6;
|
||||
mac_len = 6;
|
||||
}
|
||||
|
||||
nr_mac_rrc_data_ind(module_idP,
|
||||
@@ -486,26 +447,14 @@ int nr_process_mac_pdu(module_id_t module_idP,
|
||||
UE_info->rnti[UE_id],
|
||||
CCCH,
|
||||
pduP + mac_subheader_len,
|
||||
mac_sdu_len,
|
||||
mac_len,
|
||||
0);
|
||||
break;
|
||||
|
||||
case UL_SCH_LCID_DTCH:
|
||||
// check if LCID is valid at current time.
|
||||
if (pdu_len < sizeof(NR_MAC_SUBHEADER_SHORT))
|
||||
return 0;
|
||||
if (((NR_MAC_SUBHEADER_SHORT *)pduP)->F) {
|
||||
// mac_sdu_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8;
|
||||
if (pdu_len < sizeof(NR_MAC_SUBHEADER_LONG))
|
||||
return 0;
|
||||
mac_subheader_len = 3;
|
||||
mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L1 & 0x7f) << 8)
|
||||
| ((uint16_t)((NR_MAC_SUBHEADER_LONG *)pduP)->L2 & 0xff);
|
||||
|
||||
} else {
|
||||
mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L;
|
||||
mac_subheader_len = 2;
|
||||
}
|
||||
if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len))
|
||||
return 0;
|
||||
|
||||
LOG_D(NR_MAC, "In %s: [UE %d] %d.%d : ULSCH -> UL-%s %d (gNB %d, %d bytes)\n",
|
||||
__func__,
|
||||
@@ -515,8 +464,8 @@ int nr_process_mac_pdu(module_id_t module_idP,
|
||||
rx_lcid<4?"DCCH":"DTCH",
|
||||
rx_lcid,
|
||||
module_idP,
|
||||
mac_sdu_len);
|
||||
UE_info->mac_stats[UE_id].lc_bytes_rx[rx_lcid] += mac_sdu_len;
|
||||
mac_len);
|
||||
UE_info->mac_stats[UE_id].lc_bytes_rx[rx_lcid] += mac_len;
|
||||
|
||||
mac_rlc_data_ind(module_idP,
|
||||
UE_info->rnti[UE_id],
|
||||
@@ -526,13 +475,13 @@ int nr_process_mac_pdu(module_id_t module_idP,
|
||||
MBMS_FLAG_NO,
|
||||
rx_lcid,
|
||||
(char *)(pduP + mac_subheader_len),
|
||||
mac_sdu_len,
|
||||
mac_len,
|
||||
1,
|
||||
NULL);
|
||||
|
||||
/* Updated estimated buffer when receiving data */
|
||||
if (sched_ctrl->estimated_ul_buffer >= mac_sdu_len)
|
||||
sched_ctrl->estimated_ul_buffer -= mac_sdu_len;
|
||||
if (sched_ctrl->estimated_ul_buffer >= mac_len)
|
||||
sched_ctrl->estimated_ul_buffer -= mac_len;
|
||||
else
|
||||
sched_ctrl->estimated_ul_buffer = 0;
|
||||
break;
|
||||
@@ -547,16 +496,16 @@ int nr_process_mac_pdu(module_id_t module_idP,
|
||||
if (rx_lcid < 45 || rx_lcid == 52 || rx_lcid == 63) {
|
||||
LOG_I(NR_MAC, "In %s: dumping UL MAC SDU sub-header with length %d (LCID = 0x%02x):\n", __func__, mac_subheader_len, rx_lcid);
|
||||
log_dump(NR_MAC, pduP, mac_subheader_len, LOG_DUMP_CHAR, "\n");
|
||||
LOG_I(NR_MAC, "In %s: dumping UL MAC SDU with length %d (LCID = 0x%02x):\n", __func__, mac_sdu_len, rx_lcid);
|
||||
log_dump(NR_MAC, pduP + mac_subheader_len, mac_sdu_len, LOG_DUMP_CHAR, "\n");
|
||||
LOG_I(NR_MAC, "In %s: dumping UL MAC SDU with length %d (LCID = 0x%02x):\n", __func__, mac_len, rx_lcid);
|
||||
log_dump(NR_MAC, pduP + mac_subheader_len, mac_len, LOG_DUMP_CHAR, "\n");
|
||||
} else {
|
||||
LOG_I(NR_MAC, "In %s: dumping UL MAC CE with length %d (LCID = 0x%02x):\n", __func__, mac_ce_len, rx_lcid);
|
||||
log_dump(NR_MAC, pduP + mac_subheader_len + mac_sdu_len, mac_ce_len, LOG_DUMP_CHAR, "\n");
|
||||
LOG_I(NR_MAC, "In %s: dumping UL MAC CE with length %d (LCID = 0x%02x):\n", __func__, mac_len, rx_lcid);
|
||||
log_dump(NR_MAC, pduP + mac_subheader_len + mac_len, mac_len, LOG_DUMP_CHAR, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
pduP += ( mac_subheader_len + mac_ce_len + mac_sdu_len );
|
||||
pdu_len -= ( mac_subheader_len + mac_ce_len + mac_sdu_len );
|
||||
pduP += ( mac_subheader_len + mac_len );
|
||||
pdu_len -= ( mac_subheader_len + mac_len );
|
||||
|
||||
if (pdu_len < 0) {
|
||||
LOG_E(NR_MAC, "In %s: residual UL MAC PDU in %d.%d with length < 0!, pdu_len %d \n", __func__, frameP, slot, pdu_len);
|
||||
|
||||
@@ -445,7 +445,7 @@ typedef struct NR_UE_harq {
|
||||
|
||||
/* Transport block to be sent using this HARQ process, its size is in
|
||||
* sched_pdsch */
|
||||
uint32_t tb[16384];
|
||||
uint32_t transportBlock[16384];
|
||||
uint32_t tb_size;
|
||||
|
||||
/// sched_pdsch keeps information on MCS etc used for the initial transmission
|
||||
|
||||
@@ -89,13 +89,13 @@ void nrue_init_standalone_socket(int tx_port, int rx_port)
|
||||
int sd = socket(server_address.sin_family, SOCK_DGRAM, 0);
|
||||
if (sd < 0)
|
||||
{
|
||||
LOG_E(MAC, "Socket creation error standalone PNF\n");
|
||||
LOG_E(NR_MAC, "Socket creation error standalone PNF\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (inet_pton(server_address.sin_family, stub_eth_params.remote_addr, &server_address.sin_addr) <= 0)
|
||||
{
|
||||
LOG_E(MAC, "Invalid standalone PNF Address\n");
|
||||
LOG_E(NR_MAC, "Invalid standalone PNF Address\n");
|
||||
close(sd);
|
||||
return;
|
||||
}
|
||||
@@ -103,7 +103,7 @@ void nrue_init_standalone_socket(int tx_port, int rx_port)
|
||||
// Using connect to use send() instead of sendto()
|
||||
if (connect(sd, (struct sockaddr *)&server_address, addr_len) < 0)
|
||||
{
|
||||
LOG_E(MAC, "Connection to standalone PNF failed: %s\n", strerror(errno));
|
||||
LOG_E(NR_MAC, "Connection to standalone PNF failed: %s\n", strerror(errno));
|
||||
close(sd);
|
||||
return;
|
||||
}
|
||||
@@ -129,7 +129,7 @@ void nrue_init_standalone_socket(int tx_port, int rx_port)
|
||||
|
||||
if (bind(sd, (struct sockaddr *)&server_address, addr_len) < 0)
|
||||
{
|
||||
LOG_E(MAC, "Connection to standalone PNF failed: %s\n", strerror(errno));
|
||||
LOG_E(NR_MAC, "Connection to standalone PNF failed: %s\n", strerror(errno));
|
||||
close(sd);
|
||||
return;
|
||||
}
|
||||
@@ -634,6 +634,7 @@ static void copy_ul_tti_data_req_to_dl_info(nr_downlink_indication_t *dl_info, n
|
||||
AssertFatal(num_pdus >= 0, "Invalid ul_tti_request number of PDUS\n");
|
||||
AssertFatal(num_pdus <= sizeof(ul_tti_req->pdus_list) / sizeof(ul_tti_req->pdus_list[0]),
|
||||
"Too many pdus %d in ul_tti_req\n", num_pdus);
|
||||
|
||||
if (!send_crc_ind_and_rx_ind(sfn_slot))
|
||||
{
|
||||
LOG_T(NR_MAC, "CRC_RX ind not sent\n");
|
||||
@@ -1045,7 +1046,7 @@ void *nrue_standalone_pnf_task(void *context)
|
||||
|
||||
if (sem_post(&sfn_slot_semaphore) != 0)
|
||||
{
|
||||
LOG_E(MAC, "sem_post() error\n");
|
||||
LOG_E(NR_MAC, "sem_post() error\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
@@ -1125,13 +1126,13 @@ void update_harq_status(module_id_t module_id, uint8_t harq_pid, uint8_t ack_nac
|
||||
}
|
||||
else {
|
||||
//shouldn't get here
|
||||
LOG_E(MAC, "Trying to process acknack for an inactive harq process (%d)\n", harq_pid);
|
||||
LOG_E(NR_MAC, "Trying to process acknack for an inactive harq process (%d)\n", harq_pid);
|
||||
}
|
||||
}
|
||||
|
||||
int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){
|
||||
|
||||
NR_UE_L2_STATE_t ret;
|
||||
NR_UE_L2_STATE_t ret=0;
|
||||
module_id_t module_id = ul_info->module_id;
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
|
||||
@@ -1183,6 +1184,7 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_
|
||||
} else {
|
||||
// UL indication after reception of DCI or DL PDU
|
||||
if (dl_info && dl_info->dci_ind && dl_info->dci_ind->number_of_dcis) {
|
||||
|
||||
LOG_T(MAC,"[L2][IF MODULE][DL INDICATION][DCI_IND]\n");
|
||||
for (int i = 0; i < dl_info->dci_ind->number_of_dcis; i++) {
|
||||
LOG_T(MAC,">>>NR_IF_Module i=%d, dl_info->dci_ind->number_of_dcis=%d\n",i,dl_info->dci_ind->number_of_dcis);
|
||||
@@ -1198,8 +1200,8 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_
|
||||
|
||||
/* The check below filters out UL_DCIs (format 7) which are being processed as DL_DCIs. */
|
||||
if (dci_index->dci_format == 7 && mac->ra.ra_state == RA_SUCCEEDED) {
|
||||
LOG_T(NR_MAC, "We are filtering a UL_DCI to prevent it from being treated like a DL_DCI\n");
|
||||
break;
|
||||
LOG_D(NR_MAC, "We are filtering a UL_DCI to prevent it from being treated like a DL_DCI\n");
|
||||
continue;
|
||||
}
|
||||
dci_pdu_rel15_t *def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[dci_index->dci_format];
|
||||
g_harq_pid = def_dci_pdu_rel15->harq_pid;
|
||||
@@ -1222,7 +1224,7 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_
|
||||
|
||||
for (int i=0; i<dl_info->rx_ind->number_pdus; ++i) {
|
||||
|
||||
LOG_T(MAC, "In %s sending DL indication to MAC. 1 PDU type %d of %d total number of PDUs \n",
|
||||
LOG_D(NR_MAC, "In %s sending DL indication to MAC. 1 PDU type %d of %d total number of PDUs \n",
|
||||
__FUNCTION__,
|
||||
dl_info->rx_ind->rx_indication_body[i].pdu_type,
|
||||
dl_info->rx_ind->number_pdus);
|
||||
|
||||
@@ -969,9 +969,9 @@ rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(
|
||||
uint16_t ue_initial_id;
|
||||
uint32_t gNB_ue_ngap_id;
|
||||
rrc_gNB_ue_context_t *ue_context_p = NULL;
|
||||
protocol_ctxt_t ctxt;
|
||||
gtpv1u_gnb_create_tunnel_req_t create_tunnel_req;
|
||||
gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp;
|
||||
protocol_ctxt_t ctxt={0};
|
||||
gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0};
|
||||
gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp={0};
|
||||
uint8_t pdu_sessions_done;
|
||||
uint8_t inde_list[NR_NB_RB_MAX - 3]= {0};
|
||||
int ret = 0;
|
||||
|
||||
Reference in New Issue
Block a user