Commit 55809687 authored by cig's avatar cig Committed by Thomas Schlichter

Fixes to UE ULSCH PDU generation

- included MAC CE sub-PDUs size in the computation of RLC data to transmit
  this fixes the error with residual mac pdu appearing at gNB side when
  transmitting higher amount of data
- got rid of the nr_generate_ulsch_pdu and moved the relevant UL-SCH MAC PDU
  generation procedure within the nr_ue_get_sdu and nr_ue_get_rach
- reduced memcpy calls and unnecessary memory allocations
- fetching RLC data and SDU size from the mac_rlc_data_req, removed the call
  to mac_rlc_get_buffer_occupancy_ind
- introduced a new function to generate the MAC CEs sub-PDUs
- removed unnecessary function input parameters
- minor fixes and cleanup
- enhanced logging
parent 69577717
......@@ -390,6 +390,16 @@ typedef struct {
} NR_UE_MAC_INST_t;
typedef struct {
uint8_t power_headroom;
uint16_t crnti;
uint16_t truncated_bsr;
uint16_t short_bsr;
uint16_t long_bsr;
} NR_UE_MAC_CE_t;
typedef enum seach_space_mask_e {
type0_pdcch = 0x1,
type0a_pdcch = 0x2,
......
......@@ -156,18 +156,8 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
NR_UL_TIME_ALIGNMENT_t *ul_time_alignment,
int pdu_id);
uint16_t nr_generate_ulsch_pdu(uint8_t *sdus_payload,
uint8_t *pdu,
uint8_t num_sdus,
uint16_t *sdu_lengths,
uint8_t *sdu_lcids,
uint8_t power_headroom,
uint16_t crnti,
uint16_t truncated_bsr,
uint16_t short_bsr,
uint16_t long_bsr,
unsigned short post_padding,
uint16_t buflen);
int nr_write_ce_ulsch_pdu(unsigned char *mac_ce,
NR_UE_MAC_CE_t *nr_ue_mac_ce);
void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15);
......@@ -188,10 +178,12 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac,
uint8_t time_domain_ind,
bool use_default);
uint8_t
nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP,
sub_frame_t subframe, uint8_t eNB_index,
uint8_t *ulsch_buffer, uint16_t buflen, uint8_t *access_mode) ;
uint8_t nr_ue_get_sdu(module_id_t module_idP,
frame_t frameP,
sub_frame_t subframe,
uint8_t gNB_index,
uint8_t *ulsch_buffer,
uint16_t buflen);
int set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg, int mu,
int nrofDownlinkSlots, int nrofDownlinkSymbols,
......
......@@ -474,23 +474,19 @@ void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint
}
/////////////////////////////////////////////////////////////////////////
// This function handles:
// - Random Access Preamble Initialization (5.1.1 TS 38.321)
// - Random Access Response reception (5.1.4 TS 38.321)
/// In the current implementation, RA is 4-step contention free only
/////////////////////////////////////////////////////////////////////////
// todo TS 38.321:
// - BWP operation (subclause 5.15 TS 38.321)
// - beam failure recovery
// - handle initialization by handover
// - handle DL assignment on PDCCH for RA-RNTI
// - transmission on DCCH using PRACH (during handover, or sending SR for example)
// - take into account MAC CEs in size_sdu (currently hardcoded size to 1 MAC subPDU and 1 padding subheader)
// - fix rrc data req logic
// - retrieve TBS
// - add mac_rrc_nr_data_req_ue, etc ...
// - Msg3 Retransmissions to be scheduled by DCI 0_0
/**
* Function: handles Random Access Preamble Initialization (5.1.1 TS 38.321)
* handles Random Access Response reception (5.1.4 TS 38.321)
* Note: In the current implementation, RA is 4-step contention free only
*
* @prach_resources pointer to PRACH resources
* @prach_pdu pointer to FAPI UL PRACH PDU
* @mod_id module ID
* @CC_id CC ID
* @frame current UL TX frame
* @gNB_id gNB ID
* @nr_slot_tx current UL TX slot
*/
uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
fapi_nr_ul_config_prach_pdu *prach_pdu,
module_id_t mod_id,
......@@ -501,11 +497,10 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
RA_config_t *ra = &mac->ra;
uint8_t mac_sdus[MAX_NR_ULSCH_PAYLOAD_BYTES];
uint8_t lcid = UL_SCH_LCID_CCCH;
uint8_t *payload;
uint16_t size_sdu = 0;
unsigned short post_padding;
uint8_t sh_size = sizeof(NR_MAC_SUBHEADER_SHORT);
int8_t size_sdu = 0;
NR_RACH_ConfigCommon_t *setup;
if (mac->scc) setup = mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
else setup = mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup;
......@@ -513,11 +508,6 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric;
NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = ra->rach_ConfigDedicated;
uint8_t sdu_lcids[NB_RB_MAX] = {0};
uint16_t sdu_lengths[NB_RB_MAX] = {0};
int num_sdus = 0;
int offset = 0;
// Delay init RA procedure to allow the convergence of the IIR filter on PRACH noise measurements at gNB side
if (!prach_resources->init_msg1) {
if ( (mac->common_configuration_complete>0 || get_softmodem_params()->do_ra==1) && ((MAX_FRAME_NUMBER+frame-prach_resources->sync_frame)%MAX_FRAME_NUMBER)>150 ){
......@@ -528,22 +518,26 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
}
}
LOG_D(NR_MAC,"frame %d prach_resources->init_msg1 %d, ra->ra_state %d, ra->RA_active %d\n",
frame,prach_resources->init_msg1,ra->ra_state,ra->RA_active);
LOG_D(NR_MAC, "In %s: [UE %d][%d.%d]: init_msg1 %d, ra_state %d, RA_active %d\n",
__FUNCTION__,
mod_id,
frame,
nr_slot_tx,
prach_resources->init_msg1,
ra->ra_state,
ra->RA_active);
if (prach_resources->init_msg1 && ra->ra_state != RA_SUCCEEDED) {
if (ra->RA_active == 0) {
/* RA not active - checking if RRC is ready to initiate the RA procedure */
LOG_D(NR_MAC, "RA not active. Checking for data to transmit from upper layers...\n");
uint8_t TBS_max = 8 + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT);
payload = (uint8_t*) mac->CCCH_pdu.payload;
LOG_D(NR_MAC, "In %s: RA not active. Checking for data to transmit from upper layers...\n", __FUNCTION__);
num_sdus = 1;
post_padding = 1;
sdu_lcids[0] = lcid;
uint8_t TBS_max = 8 + 2 * sh_size;
uint8_t *pdu = (uint8_t*) mac->CCCH_pdu.payload;
NR_MAC_SUBHEADER_SHORT *header = (NR_MAC_SUBHEADER_SHORT *) pdu;
pdu += sh_size;
// initialisation by RRC
......@@ -553,57 +547,56 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
}
// CCCH PDU
size_sdu = (uint16_t) nr_mac_rrc_data_req_ue(mod_id, CC_id, gNB_id, frame, CCCH, mac_sdus);
size_sdu = nr_mac_rrc_data_req_ue(mod_id, CC_id, gNB_id, frame, CCCH, pdu);
sdu_lengths[0] = size_sdu;
LOG_D(NR_MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n", mod_id, frame, size_sdu);
LOG_D(NR_MAC, "In %s: [UE %d][%d.%d]: Requested RRCConnectionRequest, got %d bytes for LCID 0x%02x \n", __FUNCTION__, mod_id, frame, nr_slot_tx, size_sdu, lcid);
if (size_sdu > 0) {
// UE Contention Resolution Identity
// Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to determine whether or not the
// Random Access Procedure has been successful after reception of Msg4
memcpy(ra->cont_res_id, mac_sdus, sizeof(uint8_t) * 6);
memcpy(ra->cont_res_id, pdu, sizeof(uint8_t) * 6);
pdu += size_sdu;
LOG_D(NR_MAC, "In %s: [UE %d][%d.%d]: starting initialisation Random Access Procedure...\n", __FUNCTION__, mod_id, frame, nr_slot_tx);
LOG_D(NR_MAC, "[UE %d][%d.%d]: starting initialisation Random Access Procedure...\n", mod_id, frame, nr_slot_tx);
ra->Msg3_size = size_sdu + sh_size;
ra->Msg3_size = size_sdu + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT);
AssertFatal(TBS_max > ra->Msg3_size, "In %s: allocated resources are not enough for Msg3!\n", __FUNCTION__);
init_RA(mod_id, prach_resources, setup, rach_ConfigGeneric, rach_ConfigDedicated);
prach_resources->Msg3 = payload;
prach_resources->Msg3 = (uint8_t*) mac->CCCH_pdu.payload;
nr_get_RA_window(mac);
// Fill in preamble and PRACH resources
if (ra->generate_nr_prach == GENERATE_PREAMBLE) {
nr_get_prach_resources(mod_id, CC_id, gNB_id, prach_resources, prach_pdu, rach_ConfigDedicated);
}
offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus, // sdus buffer
(uint8_t *) payload, // UL MAC pdu pointer
num_sdus, // num sdus
sdu_lengths, // sdu length
sdu_lcids, // sdu lcid
0, // power headroom
0, // crnti
0, // truncated bsr
0, // short bsr
0, // long_bsr
post_padding,
0);
AssertFatal(TBS_max > offset, "Frequency resources are not enough for Msg3!\n");
header->R = 0;
header->F = 0;
header->LCID = lcid;
header->L = (unsigned char) size_sdu;
// Padding: fill remainder with 0
if (post_padding > 0){
for (int j = 0; j < (TBS_max - offset); j++)
payload[offset + j] = 0;
if (TBS_max - ra->Msg3_size > 0) {
LOG_D(NR_MAC, "In %s: remaining %d bytes, filling with padding\n", __FUNCTION__, TBS_max - ra->Msg3_size);
((NR_MAC_SUBHEADER_FIXED *) pdu)->R = 0;
((NR_MAC_SUBHEADER_FIXED *) pdu)->LCID = UL_SCH_LCID_PADDING;
pdu += sizeof(NR_MAC_SUBHEADER_FIXED);
for (int j = 0; j < TBS_max - ra->Msg3_size - sizeof(NR_MAC_SUBHEADER_FIXED); j++) {
pdu[j] = 0;
}
}
} else {
pdu -= sh_size;
}
LOG_D(MAC,"size_sdu = %i\n", size_sdu);
LOG_D(MAC,"offset = %i\n", offset);
LOG_D(NR_MAC, "In %s: dumping UL Msg3 MAC PDU with length %d: \n", __FUNCTION__, TBS_max);
for(int k = 0; k < TBS_max; k++) {
LOG_D(MAC,"(%i): %i\n", k, prach_resources->Msg3[k]);
LOG_D(NR_MAC,"(%i): %i\n", k, prach_resources->Msg3[k]);
}
// Msg3 was initialized with TBS_max bytes because the RA_Msg3_size will only be known after
......
......@@ -1137,14 +1137,6 @@ void nr_ue_send_sdu(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *u
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN);
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
LOG_T(MAC, "[UE %d] First 32 bytes of DLSCH : \n", module_idP);
for (i = 0; i < 32; i++) {
LOG_T(MAC, "%x.", sdu[i]);
}
LOG_T(MAC, "\n");
#endif
LOG_D(MAC, "In %s [%d.%d] Handling DLSCH PDU...\n", __FUNCTION__, dl_info->frame, dl_info->slot);
// Processing MAC PDU
......@@ -2149,145 +2141,116 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
}
}
////////////////////////////////////////////////////////
/////* ULSCH MAC PDU generation (6.1.2 TS 38.321) */////
////////////////////////////////////////////////////////
// about: generating MAC CEs (MAC CE and subheader) for the ULSCH PDU
// returns: number of written bytes
/**
* Function: generating MAC CEs (MAC CE and subheader) for the ULSCH PDU
* @mac_ce pointer to the MAC sub-PDUs including the MAC CEs
* @nr_ue_mac_ce pointer to the MAC CEs to be transmitted
*/
int nr_write_ce_ulsch_pdu(unsigned char *mac_ce,
NR_UE_MAC_CE_t *nr_ue_mac_ce) {
uint16_t nr_generate_ulsch_pdu(uint8_t *sdus_payload,
uint8_t *pdu,
uint8_t num_sdus,
uint16_t *sdu_lengths,
uint8_t *sdu_lcids,
uint8_t power_headroom,
uint16_t crnti,
uint16_t truncated_bsr,
uint16_t short_bsr,
uint16_t long_bsr,
unsigned short post_padding,
uint16_t buflen) {
int mac_ce_len = 0;
uint8_t mac_ce_size = 0;
NR_MAC_SUBHEADER_FIXED *mac_pdu_ptr = (NR_MAC_SUBHEADER_FIXED *) pdu;
if (nr_ue_mac_ce->power_headroom) {
LOG_D(MAC, "[UE] Generating ULSCH PDU : num_sdus %d\n", num_sdus);
LOG_D(NR_MAC, "In %s: generating PHR MAC CE with command %d\n", __FUNCTION__, nr_ue_mac_ce->power_headroom);
#ifdef DEBUG_HEADER_PARSING
// MAC CE fixed subheader
((NR_MAC_SUBHEADER_FIXED *) mac_ce)->R = 0;
((NR_MAC_SUBHEADER_FIXED *) mac_ce)->LCID = UL_SCH_LCID_SINGLE_ENTRY_PHR;
mac_ce++;
for (int i = 0; i < num_sdus; i++)
LOG_D(MAC, "[UE] MAC subPDU %d (lcid %d length %d bytes \n", i, sdu_lcids[i], sdu_lengths[i]);
// PHR MAC CE (1 octet)
((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->PH = nr_ue_mac_ce->power_headroom;
((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->R1 = 0;
((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->PCMAX = 0; // todo
((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->R2 = 0;
#endif
// update pointer and length
mac_ce_size = sizeof(NR_SINGLE_ENTRY_PHR_MAC_CE);
mac_ce += mac_ce_size;
mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED);
// Generating UL MAC subPDUs including MAC SDU and subheader
}
for (int i = 0; i < num_sdus; i++) {
LOG_D(MAC, "[UE] Generating UL MAC subPDUs for SDU with lenght %d ( num_sdus %d )\n", sdu_lengths[i], num_sdus);
if (nr_ue_mac_ce->crnti) {
if (sdu_lcids[i] != UL_SCH_LCID_CCCH){
if (sdu_lengths[i] < 128) {
((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->R = 0;
((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->F = 0;
((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->LCID = sdu_lcids[i];
((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->L = (unsigned char) sdu_lengths[i];
mac_pdu_ptr += sizeof(NR_MAC_SUBHEADER_SHORT);
} else {
((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->R = 0;
((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->F = 1;
((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->LCID = sdu_lcids[i];
((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L1 = ((unsigned short) sdu_lengths[i] >> 8) & 0x7f;
((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L2 = (unsigned short) sdu_lengths[i] & 0xff;
mac_pdu_ptr += sizeof(NR_MAC_SUBHEADER_LONG);
}
} else { // UL CCCH SDU
mac_pdu_ptr->R = 0;
mac_pdu_ptr->LCID = sdu_lcids[i];
mac_pdu_ptr ++;
}
LOG_D(NR_MAC, "In %s: generating C-RNTI MAC CE with C-RNTI %x\n", __FUNCTION__, nr_ue_mac_ce->crnti);
// cycle through SDUs, compute each relevant and place ulsch_buffer in
memcpy((void *) mac_pdu_ptr, (void *) sdus_payload, sdu_lengths[i]);
sdus_payload += sdu_lengths[i];
mac_pdu_ptr += sdu_lengths[i];
}
// MAC CE fixed subheader
((NR_MAC_SUBHEADER_FIXED *) mac_ce)->R = 0;
((NR_MAC_SUBHEADER_FIXED *) mac_ce)->LCID = UL_SCH_LCID_C_RNTI;
mac_ce++;
// Generating UL MAC subPDUs including MAC CEs (MAC CE and subheader)
// C-RNTI MAC CE (2 octets)
*(uint16_t *) mac_ce = nr_ue_mac_ce->crnti;
if (power_headroom) {
// MAC CE fixed subheader
mac_pdu_ptr->R = 0;
mac_pdu_ptr->LCID = UL_SCH_LCID_SINGLE_ENTRY_PHR;
mac_pdu_ptr++;
// update pointer and length
mac_ce_size = sizeof(uint16_t);
mac_ce += mac_ce_size;
mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED);
// PHR MAC CE (1 octet)
((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_pdu_ptr)->PH = power_headroom;
((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_pdu_ptr)->R1 = 0;
((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_pdu_ptr)->PCMAX = 0; // todo
((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_pdu_ptr)->R2 = 0;
mac_pdu_ptr += sizeof(NR_SINGLE_ENTRY_PHR_MAC_CE);
}
if (crnti) {
// MAC CE fixed subheader
mac_pdu_ptr->R = 0;
mac_pdu_ptr->LCID = UL_SCH_LCID_C_RNTI;
mac_pdu_ptr++;
if (nr_ue_mac_ce->truncated_bsr) {
// C-RNTI MAC CE (2 octets)
* (uint16_t *) mac_pdu_ptr = crnti;
mac_pdu_ptr += sizeof(uint16_t);
}
LOG_D(NR_MAC, "In %s: generating Truncated BSR MAC CE with command %x\n", __FUNCTION__, nr_ue_mac_ce->truncated_bsr);
if (truncated_bsr) {
// MAC CE fixed subheader
mac_pdu_ptr->R = 0;
mac_pdu_ptr->LCID = UL_SCH_LCID_S_TRUNCATED_BSR;
mac_pdu_ptr++;
((NR_MAC_SUBHEADER_FIXED *) mac_ce)->R = 0;
((NR_MAC_SUBHEADER_FIXED *) mac_ce)->LCID = UL_SCH_LCID_S_TRUNCATED_BSR;
mac_ce++;
// Short truncated BSR MAC CE (1 octet)
((NR_BSR_SHORT_TRUNCATED *) mac_pdu_ptr)-> Buffer_size = truncated_bsr;
((NR_BSR_SHORT_TRUNCATED *) mac_pdu_ptr)-> LcgID = 0; // todo
mac_pdu_ptr+= sizeof(NR_BSR_SHORT_TRUNCATED);
} else if (short_bsr) {
((NR_BSR_SHORT_TRUNCATED *) mac_ce)-> Buffer_size = nr_ue_mac_ce->truncated_bsr;
((NR_BSR_SHORT_TRUNCATED *) mac_ce)-> LcgID = 0;
// update pointer and length
mac_ce_size = sizeof(NR_BSR_SHORT_TRUNCATED);
mac_ce += mac_ce_size;
mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED);
} else if (nr_ue_mac_ce->short_bsr) {
LOG_D(NR_MAC, "In %s: generating Truncated short BSR MAC CE with command %x\n", __FUNCTION__, nr_ue_mac_ce->short_bsr);
// MAC CE fixed subheader
mac_pdu_ptr->R = 0;
mac_pdu_ptr->LCID = UL_SCH_LCID_S_BSR;
mac_pdu_ptr++;
((NR_MAC_SUBHEADER_FIXED *) mac_ce)->R = 0;
((NR_MAC_SUBHEADER_FIXED *) mac_ce)->LCID = UL_SCH_LCID_S_BSR;
mac_ce++;
// Short truncated BSR MAC CE (1 octet)
((NR_BSR_SHORT *) mac_pdu_ptr)->Buffer_size = short_bsr;
((NR_BSR_SHORT *) mac_pdu_ptr)->LcgID = 0; // todo
mac_pdu_ptr+= sizeof(NR_BSR_SHORT);
} else if (long_bsr) {
((NR_BSR_SHORT *) mac_ce)->Buffer_size = nr_ue_mac_ce->short_bsr;
((NR_BSR_SHORT *) mac_ce)->LcgID = 0;
// update pointer and length
mac_ce_size = sizeof(NR_BSR_SHORT);
mac_ce += mac_ce_size;
mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED);
} else if (nr_ue_mac_ce->long_bsr) {
// MAC CE variable subheader
// todo ch 6.1.3.1. TS 38.321
// ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->R = 0;
// ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->F = 0;
// ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->LCID = UL_SCH_LCID_L_BSR;
// ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->L = 0;
// last_size = 2;
// mac_pdu_ptr += last_size;
// sh_size = 2;
// Short truncated BSR MAC CE (1 octet)
// ((NR_BSR_LONG *) ce_ptr)->Buffer_size0 = short_bsr;
// ((NR_BSR_LONG *) ce_ptr)->LCGID0 = 0;
// ((NR_BSR_LONG *) mac_ce)->Buffer_size0 = short_bsr;
// ((NR_BSR_LONG *) mac_ce)->LCGID0 = 0;
// mac_ce_size = sizeof(NR_BSR_LONG); // size is variable
}
// compute offset before adding padding (if necessary)
int padding_bytes = 0;
if(buflen > 0) // If the buflen is provided
padding_bytes = buflen + pdu - (unsigned char *) mac_pdu_ptr;
AssertFatal(padding_bytes>=0,"");
return mac_ce_len;
// Compute final offset for padding
if (post_padding || padding_bytes>0) {
((NR_MAC_SUBHEADER_FIXED *) mac_pdu_ptr)->R = 0;
((NR_MAC_SUBHEADER_FIXED *) mac_pdu_ptr)->LCID = UL_SCH_LCID_PADDING;
mac_pdu_ptr++;
}
return (uint8_t *)mac_pdu_ptr-pdu;
}
/////////////////////////////////////
// Random Access Response PDU //
// TS 38.213 ch 8.2 //
......
......@@ -989,7 +989,7 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
frame_t frame_tx = ul_info->frame_tx;
slot_t slot_tx = ul_info->slot_tx;
module_id_t mod_id = ul_info->module_id;
uint8_t access_mode = SCHEDULED_ACCESS;
uint32_t gNB_index = ul_info->gNB_index;
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
RA_config_t *ra = &mac->ra;
......@@ -1036,19 +1036,18 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
// Getting IP traffic to be transmitted
data_existing = nr_ue_get_sdu(mod_id,
cc_id,
frame_tx,
slot_tx,
0,
gNB_index,
ulsch_input_buffer,
TBS_bytes,
&access_mode);
TBS_bytes);
}
LOG_D(NR_MAC,"Flipping NDI for harq_id %d\n",ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator);
mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator;
mac->first_ul_tx[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = 0;
// TBR use the proper function !
//Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity
if (!data_existing) {
//Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid
......@@ -1965,114 +1964,174 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
} // if is_nr_UL_slot
}
#define MAX_LCID 8 //Fixme: also defined in LCID table
uint8_t
nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP,
sub_frame_t subframe, uint8_t eNB_index,
uint8_t *ulsch_buffer, uint16_t buflen, uint8_t *access_mode) {
uint8_t total_rlc_pdu_header_len = 0;
#define MAX_LCID 8 // NR_MAX_NUM_LCID shall be used but the mac_rlc_data_req function can fetch data for max 8 LCID
/**
* Function: to fetch data to be transmitted from RLC, place it in the ULSCH PDU buffer
to generate the complete MAC PDU with sub-headers and MAC CEs according to ULSCH MAC PDU generation (6.1.2 TS 38.321)
the selected sub-header for the payload sub-PDUs is NR_MAC_SUBHEADER_LONG
* @module_idP Module ID
* @frameP current UL frame
* @subframe current UL slot
* @gNB_index gNB index
* @ulsch_buffer Pointer to ULSCH PDU
* @buflen TBS
*/
uint8_t nr_ue_get_sdu(module_id_t module_idP,
frame_t frameP,
sub_frame_t subframe,
uint8_t gNB_index,
uint8_t *ulsch_buffer,
uint16_t buflen) {
int16_t buflen_remain = 0;
uint8_t lcid = 0;
uint16_t sdu_lengths[MAX_LCID] = { 0 };
uint8_t sdu_lcids[MAX_LCID] = { 0 };
uint16_t payload_offset = 0, num_sdus = 0;
uint8_t ulsch_sdus[MAX_ULSCH_PAYLOAD_BYTES];
uint16_t num_sdus = 0;
uint16_t sdu_length_total = 0;
//unsigned short post_padding = 0;
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
uint8_t sh_size = sizeof(NR_MAC_SUBHEADER_LONG);
// Pointer used to build the MAC PDU by placing the RLC SDUs in the ULSCH buffer
uint8_t *pdu = ulsch_buffer;
// Preparing the MAC CEs sub-PDUs and get the total size
unsigned char mac_header_control_elements[16] = {0};
NR_UE_MAC_CE_t nr_ue_mac_ce = {.crnti = mac->crnti};
int tot_mac_ce_len = nr_write_ce_ulsch_pdu(&mac_header_control_elements[0], &nr_ue_mac_ce);
uint8_t total_mac_pdu_header_len = tot_mac_ce_len;
rlc_buffer_occupancy_t lcid_buffer_occupancy_new = 0;
LOG_D(NR_MAC,
"[UE %d] MAC PROCESS UL TRANSPORT BLOCK at frame%d subframe %d TBS=%d\n",
module_idP, frameP, subframe, buflen);
AssertFatal(CC_id == 0,
"Transmission on secondary CCs is not supported yet\n");
LOG_D(NR_MAC, "In %s: [UE %d] [%d.%d] process UL transport block at with size TBS = %d bytes \n", __FUNCTION__, module_idP, frameP, subframe, buflen);
// Check for DCCH first
// TO DO: Multiplex in the order defined by the logical channel prioritization
for (lcid = UL_SCH_LCID_SRB1;
lcid < MAX_LCID; lcid++) {
lcid_buffer_occupancy_new = mac_rlc_get_buffer_occupancy_ind(module_idP, mac->crnti, eNB_index, frameP, subframe, ENB_FLAG_NO, lcid);
if(lcid_buffer_occupancy_new) {
buflen_remain =
buflen - (total_rlc_pdu_header_len + sdu_length_total + MAX_RLC_SDU_SUBHEADER_SIZE);
LOG_D(NR_MAC,
"[UE %d] Frame %d : UL-DXCH -> ULSCH, RLC %d has %d bytes to "
"send (Transport Block size %d SDU Length Total %d , mac header len %d, buflen_remain %d )\n", //BSR byte before Tx=%d
module_idP, frameP, lcid, lcid_buffer_occupancy_new,
buflen, sdu_length_total,
total_rlc_pdu_header_len, buflen_remain); // ,nr_ue_mac_inst->scheduling_info.BSR_bytes[nr_ue_mac_inst->scheduling_info.LCGID[lcid]]
while(buflen_remain > 0 && lcid_buffer_occupancy_new){
sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
mac->crnti,
eNB_index,
frameP,
ENB_FLAG_NO,
MBMS_FLAG_NO,
lcid,
buflen_remain-MAX_RLC_SDU_SUBHEADER_SIZE,
//Fixme: Laurent I removed MAX_RLC_SDU_SUBHEADER_SIZE because else we get out the buffer silently
// the interface with nr_generate_ulsch_pdu() looks over complex and not CPU optimized
(char *)&ulsch_sdus[sdu_length_total],0,
0);
AssertFatal(buflen_remain >= sdu_lengths[num_sdus],
"LCID=%d RLC has segmented %d bytes but MAC has max=%d\n",
lcid, sdu_lengths[num_sdus], buflen_remain);
if (sdu_lengths[num_sdus]) {
sdu_length_total += sdu_lengths[num_sdus];
sdu_lcids[num_sdus] = lcid;
total_rlc_pdu_header_len += MAX_RLC_SDU_SUBHEADER_SIZE; //rlc_pdu_header_len_last;
//Update number of SDU
num_sdus++;
}
/* Get updated BO after multiplexing this PDU */
lcid_buffer_occupancy_new = mac_rlc_get_buffer_occupancy_ind(module_idP,mac->crnti,eNB_index,frameP, subframe, ENB_FLAG_NO, lcid);
buflen_remain = buflen - (total_rlc_pdu_header_len + sdu_length_total + MAX_RLC_SDU_SUBHEADER_SIZE);
buflen_remain = buflen - (total_mac_pdu_header_len + sdu_length_total + MAX_RLC_SDU_SUBHEADER_SIZE);
LOG_D(NR_MAC, "In %s: [UE %d] [%d.%d] UL-DXCH -> ULSCH, RLC with LCID 0x%02x (TBS %d bytes, sdu_length_total %d bytes, MAC header len %d bytes, buflen_remain %d bytes)\n",
__FUNCTION__,
module_idP,
frameP,
subframe,
lcid,
buflen,
sdu_length_total,
tot_mac_ce_len,
buflen_remain);
while (buflen_remain > 0){
// Pointer used to build the MAC sub-PDU headers in the ULSCH buffer for each SDU
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) pdu;
pdu += sh_size;
sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
mac->crnti,
gNB_index,
frameP,
ENB_FLAG_NO,
MBMS_FLAG_NO,
lcid,
buflen_remain,
(char *)pdu,
0,
0);
AssertFatal(buflen_remain >= sdu_lengths[num_sdus], "In %s: LCID = 0x%02x RLC has segmented %d bytes but MAC has max %d remaining bytes\n",
__FUNCTION__,
lcid,
sdu_lengths[num_sdus],
buflen_remain);
if (sdu_lengths[num_sdus]) {
LOG_D(MAC, "In %s: Generating UL MAC sub-PDU for SDU %d, length %d bytes, RB with LCID 0x%02x (buflen (TBS) %d bytes)\n", __FUNCTION__,
num_sdus + 1,
sdu_lengths[num_sdus],
lcid,
buflen);
header->R = 0;
header->F = 1;
header->LCID = lcid;
header->L1 = ((unsigned short) sdu_lengths[num_sdus] >> 8) & 0x7f;
header->L2 = (unsigned short) sdu_lengths[num_sdus] & 0xff;
#ifdef ENABLE_MAC_PAYLOAD_DEBUG
LOG_I(NR_MAC, "In %s: dumping MAC sub-header with length %d: \n", __FUNCTION__, sh_size);
log_dump(NR_MAC, header, sh_size, LOG_DUMP_CHAR, "\n");
LOG_I(NR_MAC, "In %s: dumping MAC SDU with length %d \n", __FUNCTION__, sdu_lengths[num_sdus]);
log_dump(NR_MAC, pdu, sdu_lengths[num_sdus], LOG_DUMP_CHAR, "\n");
#endif
pdu += sdu_lengths[num_sdus];
sdu_length_total += sdu_lengths[num_sdus];
total_mac_pdu_header_len += sh_size;
num_sdus++;
} else {
pdu -= sh_size;
LOG_D(MAC, "In %s: no data to transmit for RB with LCID 0x%02x\n", __FUNCTION__, lcid);
break;
}
buflen_remain = buflen - (total_mac_pdu_header_len + sdu_length_total + MAX_RLC_SDU_SUBHEADER_SIZE);
}
}
// Generate ULSCH PDU
if (num_sdus>0) {
payload_offset = nr_generate_ulsch_pdu(ulsch_sdus,
ulsch_buffer, // mac header
num_sdus, // num sdus
sdu_lengths, // sdu length
sdu_lcids, // sdu lcid
0, // power_headroom
mac->crnti, // crnti
0, // truncated_bsr
0, // short_bsr
0, // long_bsr
0, // post_padding
buflen); // TBS in bytes
} else {
return 0;
}
if (num_sdus > 0) {
// Padding: fill remainder of ULSCH with 0
if (buflen - payload_offset > 0){
for (int j = payload_offset; j < buflen; j++)
ulsch_buffer[j] = 0;
}
if (tot_mac_ce_len > 0) {
LOG_D(NR_MAC, "In %s copying %d bytes of MAC CEs to the UL PDU \n", __FUNCTION__, tot_mac_ce_len);
memcpy((void *) pdu, (void *) mac_header_control_elements, tot_mac_ce_len);
buflen_remain = buflen - (total_mac_pdu_header_len + sdu_length_total);
pdu += (unsigned char) tot_mac_ce_len;
#ifdef ENABLE_MAC_PAYLOAD_DEBUG
LOG_I(NR_MAC, "In %s: dumping MAC CE with length tot_mac_ce_len %d: \n", __FUNCTION__, tot_mac_ce_len);
log_dump(NR_MAC, mac_header_control_elements, tot_mac_ce_len, LOG_DUMP_CHAR, "\n");
#endif
}
// Compute final offset for padding and fill remainder of ULSCH with 0
if (buflen_remain > 0) {
((NR_MAC_SUBHEADER_FIXED *) pdu)->R = 0;
((NR_MAC_SUBHEADER_FIXED *) pdu)->LCID = UL_SCH_LCID_PADDING;
#ifdef ENABLE_MAC_PAYLOAD_DEBUG
LOG_I(NR_MAC, "In %s: padding MAC sub-header with length %ld bytes \n", __FUNCTION__, sizeof(NR_MAC_SUBHEADER_FIXED));
log_dump(NR_MAC, pdu, sizeof(NR_MAC_SUBHEADER_FIXED), LOG_DUMP_CHAR, "\n");
#endif
pdu++;
buflen_remain--;
for (int j = 0; j < buflen_remain; j++) {
pdu[j] = 0;
}
#ifdef ENABLE_MAC_PAYLOAD_DEBUG
LOG_I(NR_MAC, "In %s: MAC padding sub-PDU with length %d bytes \n", __FUNCTION__, buflen_remain);
log_dump(NR_MAC, pdu, buflen_remain, LOG_DUMP_CHAR, "\n");
#endif
}
#ifdef ENABLE_MAC_PAYLOAD_DEBUG
LOG_I(NR_MAC, "In %s: dumping MAC PDU with length %d: \n", __FUNCTION__, buflen);
log_dump(NR_MAC, ulsch_buffer, buflen, LOG_DUMP_CHAR, "\n");
#endif
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
LOG_I(NR_MAC, "Printing UL MAC payload UE side, payload_offset: %d \n", payload_offset);
for (int i = 0; i < buflen ; i++) {
//harq_process_ul_ue->a[i] = (unsigned char) rand();
//printf("a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]);
printf("%02x ",(unsigned char)ulsch_buffer[i]);
}
printf("\n");
#endif
return 1;
return num_sdus > 0 ? 1 : 0;
}
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