Commit 45be0a56 authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/fix-ulsch-bsr' into integration_2024_w46 (!2991)

fix BSR report malformed, add SHORT BSR when it can (instead of LONG BSR)...

fix BSR report malformed, add SHORT BSR when it can (instead of LONG BSR)
simplify the code and make the code more explicit, but the may structure
remain (nr_write_ce_ulsch_pdu interface is complex, merging it into the
called would make simpler and more interstandable code), fix some asserts
related to this part of code
parents ca119de0 2348b3c0
......@@ -122,6 +122,11 @@ static inline int get_mac_len(uint8_t *pdu, uint32_t pdu_len, uint16_t *mac_ce_l
*mac_subheader_len = sizeof(*s);
*mac_ce_len = s->L;
}
if (*mac_ce_len > pdu_len) {
LOG_E(NR_MAC, "MAC sdu len impossible (%d)\n", *mac_ce_len);
return false;
}
return true;
}
......@@ -133,8 +138,6 @@ typedef struct {
uint8_t LcgID: 3; // octet 1 MSB
} __attribute__ ((__packed__)) NR_BSR_SHORT;
typedef NR_BSR_SHORT NR_BSR_SHORT_TRUNCATED;
// Long BSR for all logical channel group ID
typedef struct {
uint8_t LcgID0: 1; // octet 1 [0]
......@@ -145,18 +148,8 @@ typedef struct {
uint8_t LcgID5: 1; // octet 1 [5]
uint8_t LcgID6: 1; // octet 1 [6]
uint8_t LcgID7: 1; // octet 1 [7]
uint8_t Buffer_size0: 8; // octet 2 [7:0]
uint8_t Buffer_size1: 8; // octet 3 [7:0]
uint8_t Buffer_size2: 8; // octet 4 [7:0]
uint8_t Buffer_size3: 8; // octet 5 [7:0]
uint8_t Buffer_size4: 8; // octet 6 [7:0]
uint8_t Buffer_size5: 8; // octet 7 [7:0]
uint8_t Buffer_size6: 8; // octet 8 [7:0]
uint8_t Buffer_size7: 8; // octet 9 [7:0]
} __attribute__ ((__packed__)) NR_BSR_LONG;
typedef NR_BSR_LONG NR_BSR_LONG_TRUNCATED;
// 38.321 ch. 6.1.3.4
typedef struct {
uint8_t TA_COMMAND: 6; // octet 1 [5:0]
......
......@@ -71,7 +71,6 @@
#define NR_BSR_TRIGGER_NONE (0) /* No BSR Trigger */
#define NR_BSR_TRIGGER_REGULAR (1) /* For Regular and ReTxBSR Expiry Triggers */
#define NR_BSR_TRIGGER_PERIODIC (2) /* For BSR Periodic Timer Expiry Trigger */
#define NR_BSR_TRIGGER_PADDING (4) /* For Padding BSR Trigger */
#define NR_INVALID_LCGID (NR_MAX_NUM_LCGID)
......@@ -194,8 +193,6 @@ typedef enum {
typedef struct {
// after multiplexing buffer remain for each lcid
int32_t LCID_buffer_remain;
// buffer status for each lcid
bool LCID_buffer_with_data;
// logical channel group id of this LCID
long LCGID;
// Bj bucket usage per lcid
......@@ -203,13 +200,6 @@ typedef struct {
NR_timer_t Bj_timer;
} NR_LC_SCHEDULING_INFO;
typedef struct {
// buffer status for each lcgid
uint8_t BSR; // should be more for mesh topology
// keep the number of bytes in rlc buffer for each lcgid
int32_t BSR_bytes;
} NR_LCG_SCHEDULING_INFO;
typedef struct {
bool active_SR_ID;
/// SR pending as defined in 38.321
......@@ -244,8 +234,6 @@ typedef struct {
typedef struct {
// lcs scheduling info
NR_LC_SCHEDULING_INFO lc_sched_info[NR_MAX_NUM_LCID];
// lcg scheduling info
NR_LCG_SCHEDULING_INFO lcg_sched_info[NR_MAX_NUM_LCGID];
// SR INFO
nr_sr_info_t sr_info[NR_MAX_SR_ID];
/// BSR report flag management
......
......@@ -172,13 +172,22 @@ void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, in
void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac,nr_downlink_indication_t *dl_info, int pdu_id);
typedef struct {
union {
NR_BSR_SHORT s;
NR_BSR_LONG l;
uint8_t lcg_bsr[8];
} bsr;
enum { b_none, b_long, b_short, b_short_trunc, b_long_trunc } type_bsr;
} type_bsr_t;
int nr_write_ce_msg3_pdu(uint8_t *mac_ce, NR_UE_MAC_INST_t *mac, rnti_t crnti, uint8_t *mac_ce_end);
int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
NR_UE_MAC_INST_t *mac,
NR_SINGLE_ENTRY_PHR_MAC_CE *power_headroom,
uint16_t *crnti,
NR_BSR_SHORT *truncated_bsr,
NR_BSR_SHORT *short_bsr,
NR_BSR_LONG *long_bsr);
const type_bsr_t *bsr,
uint8_t *mac_ce_end);
void config_dci_pdu(NR_UE_MAC_INST_t *mac,
fapi_nr_dl_config_request_t *dl_config,
......@@ -188,16 +197,6 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac,
void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl_config, const frame_t frame, const int slot);
uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
int cc_id,
frame_t frameP,
sub_frame_t subframe,
uint8_t gNB_index,
uint8_t *ulsch_buffer,
uint32_t buflen,
int16_t tx_power,
int16_t P_CMAX);
void set_harq_status(NR_UE_MAC_INST_t *mac,
uint8_t pucch_id,
uint8_t harq_id,
......
......@@ -192,7 +192,6 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
for (int i = 0; i < NR_MAX_NUM_LCID; i++) {
LOG_D(NR_MAC, "Applying default logical channel config for LCID %d\n", i);
nr_mac->scheduling_info.lc_sched_info[i].Bj = 0;
nr_mac->scheduling_info.lc_sched_info[i].LCID_buffer_with_data = false;
nr_mac->scheduling_info.lc_sched_info[i].LCID_buffer_remain = 0;
}
......
......@@ -785,7 +785,7 @@ void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB
} else if (!IS_SA_MODE(get_softmodem_params())) {
uint8_t temp_pdu[16] = {0};
size_sdu = nr_write_ce_ulsch_pdu(temp_pdu, mac, 0, &(mac->crnti), NULL, NULL, NULL);
size_sdu = nr_write_ce_msg3_pdu(temp_pdu, mac, mac->crnti, temp_pdu + sizeof(temp_pdu));
ra->Msg3_size = size_sdu;
}
} else if (ra->RA_window_cnt != -1) { // RACH is active
......
......@@ -2524,7 +2524,7 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *p
AssertFatal(sr_count < 2, "Cannot handle more than 1 SR per slot yet\n");
}
}
return sr_count > 0 ? true : false;
return sr_count > 0;
}
int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id)
......@@ -2537,12 +2537,14 @@ int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_Schedu
return 0;
}
LOG_D(NR_MAC, "[UE %d] Frame %d slot %d SR %s for ID %ld\n",
LOG_D(NR_MAC,
"[UE %d] Frame %d slot %d SR %s for ID %ld, timer %d\n",
mac->ue_id,
frame,
slot,
sr_info->pending ? "pending" : "not pending",
sr_id); // todo
sr_id, // todo
nr_timer_is_active(&sr_info->prohibitTimer));
// TODO check if the PUCCH resource for the SR transmission occasion does not overlap with a UL-SCH resource
if (!sr_info->pending || nr_timer_is_active(&sr_info->prohibitTimer))
......@@ -3772,9 +3774,23 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i
}
}
int nr_write_ce_msg3_pdu(uint8_t *mac_ce, NR_UE_MAC_INST_t *mac, rnti_t crnti, uint8_t *mac_ce_end)
{
uint8_t *pdu = mac_ce;
if (IS_SA_MODE(get_softmodem_params()) && mac->ra.ra_state != nrRA_SUCCEEDED) {
LOG_D(NR_MAC, "Generating C-RNTI MAC CE with C-RNTI %x\n", crnti);
*(NR_MAC_SUBHEADER_FIXED *)mac_ce = (NR_MAC_SUBHEADER_FIXED){.R = 0, .LCID = UL_SCH_LCID_C_RNTI};
mac_ce += sizeof(NR_MAC_SUBHEADER_FIXED);
// C-RNTI MAC CE (2 octets)
memcpy(mac_ce, &crnti, sizeof(crnti));
// update pointer and length
mac_ce += sizeof(crnti);
}
return mac_ce - pdu;
}
/**
* Function: generating MAC CEs (MAC CE and subheader) for the ULSCH PDU
* Notes: TODO: PHR and BSR reporting
* Parameters:
* @mac_ce pointer to the MAC sub-PDUs including the MAC CEs
* @mac pointer to the MAC instance
......@@ -3783,158 +3799,98 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i
int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
NR_UE_MAC_INST_t *mac,
NR_SINGLE_ENTRY_PHR_MAC_CE *power_headroom,
uint16_t *crnti,
NR_BSR_SHORT *truncated_bsr,
NR_BSR_SHORT *short_bsr,
NR_BSR_LONG *long_bsr)
const type_bsr_t *bsr,
uint8_t *mac_ce_end)
{
int mac_ce_len = 0;
uint8_t *pdu = mac_ce;
if (power_headroom) {
// 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++;
// PHR MAC CE (1 octet)
((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->PH = power_headroom->PH;
((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->R1 = 0;
((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->PCMAX = power_headroom->PCMAX;
((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->R2 = 0;
// update pointer and length
int 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);
*(NR_MAC_SUBHEADER_FIXED *)mac_ce = (NR_MAC_SUBHEADER_FIXED){.R = 0, .LCID = UL_SCH_LCID_SINGLE_ENTRY_PHR};
mac_ce += sizeof(NR_MAC_SUBHEADER_FIXED);
*(NR_SINGLE_ENTRY_PHR_MAC_CE *)mac_ce = *power_headroom;
mac_ce += sizeof(NR_SINGLE_ENTRY_PHR_MAC_CE);
LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : power_headroom pdu %p mac_ce %p b\n",
pdu, mac_ce);
}
if (crnti && (!IS_SA_MODE(get_softmodem_params()) && get_softmodem_params()->do_ra && mac->ra.ra_state != nrRA_SUCCEEDED)) {
LOG_D(NR_MAC, "In %s: generating C-RNTI MAC CE with C-RNTI %x\n", __FUNCTION__, (*crnti));
// 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++;
// C-RNTI MAC CE (2 octets)
memcpy(mac_ce, crnti, sizeof(*crnti));
// update pointer and length
int mac_ce_size = sizeof(uint16_t);
mac_ce += mac_ce_size;
mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED);
}
if (truncated_bsr) {
// MAC CE fixed subheader
((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_ce)-> Buffer_size = truncated_bsr->Buffer_size;
((NR_BSR_SHORT_TRUNCATED *) mac_ce)-> LcgID = truncated_bsr->LcgID;;
// update pointer and length
int mac_ce_size = sizeof(NR_BSR_SHORT_TRUNCATED);
mac_ce += mac_ce_size;
mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED);
LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : truncated_bsr Buffer_size %d LcgID %d pdu %p mac_ce %p\n",
truncated_bsr->Buffer_size, truncated_bsr->LcgID, pdu, mac_ce);
} else if (short_bsr) {
// MAC CE fixed subheader
((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_ce)->Buffer_size = short_bsr->Buffer_size;
((NR_BSR_SHORT *) mac_ce)->LcgID = short_bsr->LcgID;
// update pointer and length
int mac_ce_size = sizeof(NR_BSR_SHORT);
mac_ce += mac_ce_size;
mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED);
LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : short_bsr Buffer_size %d LcgID %d pdu %p mac_ce %p\n",
short_bsr->Buffer_size, short_bsr->LcgID, pdu, mac_ce);
} else if (long_bsr) {
// MAC CE variable subheader
switch (bsr->type_bsr) {
case b_short:
case b_short_trunc: {
*(NR_MAC_SUBHEADER_FIXED *)mac_ce =
(NR_MAC_SUBHEADER_FIXED){.R = 0, .LCID = bsr->type_bsr == b_short ? UL_SCH_LCID_S_BSR : UL_SCH_LCID_S_TRUNCATED_BSR};
mac_ce += sizeof(NR_MAC_SUBHEADER_FIXED);
*(NR_BSR_SHORT *)mac_ce = bsr->bsr.s;
mac_ce += sizeof(NR_BSR_SHORT);
LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : bsr Buffer_size %d LcgID %d \n", bsr->bsr.s.Buffer_size, bsr->bsr.s.LcgID);
} break;
case b_long:
case b_long_trunc: {
// ch 6.1.3.1. TS 38.321
((NR_MAC_SUBHEADER_SHORT *) mac_ce)->R = 0;
((NR_MAC_SUBHEADER_SHORT *) mac_ce)->F = 0;
((NR_MAC_SUBHEADER_SHORT *) mac_ce)->LCID = UL_SCH_LCID_L_BSR;
NR_MAC_SUBHEADER_SHORT *mac_pdu_subheader_ptr = (NR_MAC_SUBHEADER_SHORT *) mac_ce;
mac_ce += 2;
NR_MAC_SUBHEADER_SHORT *mac_pdu_subheader_ptr = (NR_MAC_SUBHEADER_SHORT *)mac_ce;
mac_ce += sizeof(NR_MAC_SUBHEADER_SHORT);
uint8_t *mark = mac_ce;
// Could move to nr_get_sdu()
uint8_t *Buffer_size_ptr= (uint8_t*) mac_ce + 1;
//int NR_BSR_LONG_SIZE = 1;
if (long_bsr->Buffer_size0 == 0) {
((NR_BSR_LONG *) mac_ce)->LcgID0 = 0;
} else {
((NR_BSR_LONG *) mac_ce)->LcgID0 = 1;
*Buffer_size_ptr++ = long_bsr->Buffer_size0;
}
if (long_bsr->Buffer_size1 == 0) {
((NR_BSR_LONG *) mac_ce)->LcgID1 = 0;
} else {
((NR_BSR_LONG *) mac_ce)->LcgID1 = 1;
*Buffer_size_ptr++ = long_bsr->Buffer_size1;
}
if (long_bsr->Buffer_size2 == 0) {
((NR_BSR_LONG *) mac_ce)->LcgID2 = 0;
} else {
((NR_BSR_LONG *) mac_ce)->LcgID2 = 1;
*Buffer_size_ptr++ = long_bsr->Buffer_size2;
}
if (long_bsr->Buffer_size3 == 0) {
((NR_BSR_LONG *) mac_ce)->LcgID3 = 0;
} else {
((NR_BSR_LONG *) mac_ce)->LcgID3 = 1;
*Buffer_size_ptr++ = long_bsr->Buffer_size3;
}
if (long_bsr->Buffer_size4 == 0) {
((NR_BSR_LONG *) mac_ce)->LcgID4 = 0;
} else {
((NR_BSR_LONG *) mac_ce)->LcgID4 = 1;
*Buffer_size_ptr++ = long_bsr->Buffer_size4;
}
if (long_bsr->Buffer_size5 == 0) {
((NR_BSR_LONG *) mac_ce)->LcgID5 = 0;
} else {
((NR_BSR_LONG *) mac_ce)->LcgID5 = 1;
*Buffer_size_ptr++ = long_bsr->Buffer_size5;
}
if (long_bsr->Buffer_size6 == 0) {
((NR_BSR_LONG *) mac_ce)->LcgID6 = 0;
} else {
((NR_BSR_LONG *) mac_ce)->LcgID6 = 1;
*Buffer_size_ptr++ = long_bsr->Buffer_size6;
}
if (long_bsr->Buffer_size7 == 0) {
((NR_BSR_LONG *) mac_ce)->LcgID7 = 0;
} else {
((NR_BSR_LONG *) mac_ce)->LcgID7 = 1;
*Buffer_size_ptr++ = long_bsr->Buffer_size7;
}
int mac_ce_size = ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_subheader_ptr)->L = (uint8_t*) Buffer_size_ptr - (uint8_t*) mac_ce;
LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : long_bsr size %d Lcgbit 0x%02x Buffer_size %d %d %d %d %d %d %d %d\n", mac_ce_size, *((uint8_t*) mac_ce),
((NR_BSR_LONG *) mac_ce)->Buffer_size0, ((NR_BSR_LONG *) mac_ce)->Buffer_size1, ((NR_BSR_LONG *) mac_ce)->Buffer_size2, ((NR_BSR_LONG *) mac_ce)->Buffer_size3,
((NR_BSR_LONG *) mac_ce)->Buffer_size4, ((NR_BSR_LONG *) mac_ce)->Buffer_size5, ((NR_BSR_LONG *) mac_ce)->Buffer_size6, ((NR_BSR_LONG *) mac_ce)->Buffer_size7);
mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_SHORT);
NR_BSR_LONG *ceLong = (NR_BSR_LONG *)mac_ce;
*ceLong = (NR_BSR_LONG){0};
mac_ce += sizeof(NR_BSR_LONG);
// int NR_BSR_LONG_SIZE = 1;
if (bsr->bsr.lcg_bsr[0] && mac_ce < mac_ce_end) {
ceLong->LcgID0 = 1;
*mac_ce++ = bsr->bsr.lcg_bsr[0];
}
if (bsr->bsr.lcg_bsr[1] && mac_ce < mac_ce_end) {
ceLong->LcgID1 = 1;
*mac_ce++ = bsr->bsr.lcg_bsr[1];
}
if (bsr->bsr.lcg_bsr[2] && mac_ce < mac_ce_end) {
ceLong->LcgID2 = 1;
*mac_ce++ = bsr->bsr.lcg_bsr[2];
}
if (bsr->bsr.lcg_bsr[3] && mac_ce < mac_ce_end) {
ceLong->LcgID3 = 1;
*mac_ce++ = bsr->bsr.lcg_bsr[3];
}
if (bsr->bsr.lcg_bsr[4] && mac_ce < mac_ce_end) {
ceLong->LcgID4 = 1;
*mac_ce++ = bsr->bsr.lcg_bsr[4];
}
if (bsr->bsr.lcg_bsr[5] && mac_ce < mac_ce_end) {
ceLong->LcgID5 = 1;
*mac_ce++ = bsr->bsr.lcg_bsr[5];
}
if (bsr->bsr.lcg_bsr[6] && mac_ce < mac_ce_end) {
ceLong->LcgID6 = 1;
*mac_ce++ = bsr->bsr.lcg_bsr[6];
}
if (bsr->bsr.lcg_bsr[7] && mac_ce < mac_ce_end) {
ceLong->LcgID7 = 1;
*mac_ce++ = bsr->bsr.lcg_bsr[7];
}
*mac_pdu_subheader_ptr =
(NR_MAC_SUBHEADER_SHORT){.LCID = bsr->type_bsr == b_long ? UL_SCH_LCID_L_BSR : UL_SCH_LCID_L_TRUNCATED_BSR,
.L = mac_ce - mark};
LOG_D(NR_MAC,
"[UE] Generating ULSCH PDU : long_bsr size %d Lcgbit 0x%02x Buffer_size %d %d %d %d %d %d %d %d\n",
((NR_MAC_SUBHEADER_SHORT *)mac_pdu_subheader_ptr)->L,
*mac_ce,
bsr->bsr.lcg_bsr[0],
bsr->bsr.lcg_bsr[1],
bsr->bsr.lcg_bsr[2],
bsr->bsr.lcg_bsr[3],
bsr->bsr.lcg_bsr[4],
bsr->bsr.lcg_bsr[5],
bsr->bsr.lcg_bsr[6],
bsr->bsr.lcg_bsr[7]);
} break;
case b_none:
break;
default:
DevAssert(false);
}
return mac_ce_len;
return mac_ce - pdu;
}
/////////////////////////////////////
// Random Access Response PDU //
// TS 38.213 ch 8.2 //
......
......@@ -68,6 +68,16 @@ static void nr_ue_fill_phr(NR_UE_MAC_INST_t *mac,
float tx_power,
frame_t frameP,
sub_frame_t subframe);
static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
int cc_id,
frame_t frameP,
sub_frame_t subframe,
uint8_t gNB_index,
uint8_t *ulsch_buffer,
const uint32_t buflen,
int tx_power,
int P_MAX,
bool *BSRsent);
void clear_ul_config_request(NR_UE_MAC_INST_t *mac, int scs)
{
......@@ -865,8 +875,8 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
if (pusch_config_pdu->scid == 0 && NR_DMRS_ulconfig && NR_DMRS_ulconfig->transformPrecodingDisabled &&
NR_DMRS_ulconfig->transformPrecodingDisabled->scramblingID0)
pusch_config_pdu->ul_dmrs_scrambling_id = *NR_DMRS_ulconfig->transformPrecodingDisabled->scramblingID0;
if (pusch_config_pdu->scid == 1 && NR_DMRS_ulconfig &&
NR_DMRS_ulconfig->transformPrecodingDisabled->scramblingID1)
if (pusch_config_pdu->scid == 1 && NR_DMRS_ulconfig && NR_DMRS_ulconfig->transformPrecodingDisabled
&& NR_DMRS_ulconfig->transformPrecodingDisabled->scramblingID1)
pusch_config_pdu->ul_dmrs_scrambling_id = *NR_DMRS_ulconfig->transformPrecodingDisabled->scramblingID1;
}
......@@ -1386,20 +1396,28 @@ void schedule_RA_after_SR_failure(NR_UE_MAC_INST_t *mac)
// TODO we don't have semi-persistent CSI reporting
}
static void nr_update_sr(NR_UE_MAC_INST_t *mac)
static void nr_update_sr(NR_UE_MAC_INST_t *mac, bool BSRsent)
{
NR_UE_SCHEDULING_INFO *sched_info = &mac->scheduling_info;
// if no pending data available for transmission
// All pending SR(s) shall be cancelled and each respective sr-ProhibitTimer shall be stopped
bool data_avail = false;
for (int i = 0; i < NR_MAX_NUM_LCID; i++) {
if (sched_info->lc_sched_info[i].LCID_buffer_remain > 0) {
data_avail = true;
break;
}
// in TS 38.321:
// The SR configuration of the logical channel that triggered the BSR
// (subclause 5.4.5) (if such a configuration exists) is considered as corresponding SR configuration for the triggered SR
// in the hereafter code, we compute actual state at the time we compute the SR
// So, it might be more accurate than the logical channel that triggered the BSR some slots ago if new data came in the UE for
// ULSCH
nr_lcordered_info_t *lc_info = NULL;
for (int idx = 0; idx < mac->lc_ordered_list.count && lc_info == NULL; idx++) {
nr_lcordered_info_t *lc_info_loop = mac->lc_ordered_list.array[idx];
NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lc_info_loop->lcid);
if (lc_sched_info->LCID_buffer_remain)
lc_info = lc_info_loop;
}
if (!data_avail) {
if (lc_info == NULL) { // all queues are empty
for (int i = 0; i < NR_MAX_SR_ID; i++) {
nr_sr_info_t *sr = &sched_info->sr_info[i];
if (sr->active_SR_ID) {
......@@ -1409,22 +1427,19 @@ static void nr_update_sr(NR_UE_MAC_INST_t *mac)
nr_timer_stop(&sr->prohibitTimer);
}
}
return;
}
// if a Regular BSR has been triggered and logicalChannelSR-DelayTimer is not running
if (((sched_info->BSR_reporting_active & NR_BSR_TRIGGER_REGULAR) == 0)
|| nr_timer_is_active(&sched_info->sr_DelayTimer))
if (BSRsent || nr_timer_is_active(&sched_info->sr_DelayTimer))
return;
nr_lcordered_info_t *lc_info = get_lc_info_from_lcid(mac, sched_info->regularBSR_trigger_lcid);
AssertFatal(lc_info, "Couldn't find logical channel with LCID %ld\n", sched_info->regularBSR_trigger_lcid);
// if there is no UL-SCH resource available for a new transmission (ie we are at this point)
// if the MAC entity is configured with configured uplink grant(s) and the Regular BSR was triggered for a
// logical channel for which logicalChannelSR-Mask is set to false or
if (mac->current_UL_BWP->configuredGrantConfig && lc_info->lc_SRMask)
return;
// if the UL-SCH resources available for a new transmission do not meet the LCP mapping restrictions
// TODO not implemented
......@@ -1440,8 +1455,7 @@ static void nr_update_sr(NR_UE_MAC_INST_t *mac)
LOG_D(NR_MAC, "Triggering SR for ID %d\n", lc_info->sr_id);
sr->pending = true;
sr->counter = 0;
}
else {
} else {
// initiate a Random Access procedure on the SpCell and cancel the pending SR
// if the MAC entity has no valid PUCCH resource configured for the pending SR
sr->pending = false;
......@@ -1453,68 +1467,66 @@ static void nr_update_sr(NR_UE_MAC_INST_t *mac)
}
}
static void nr_update_bsr(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP, uint8_t gNB_index)
static void nr_update_rlc_buffers_status(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP, uint8_t gNB_index)
{
// Reset All BSR Infos
for (int id = 0; id < NR_MAX_NUM_LCID; id++) {
// Reset transmission status
mac->scheduling_info.lc_sched_info[id].LCID_buffer_with_data = false;
}
for (int lcgid = 0; lcgid < NR_MAX_NUM_LCGID; lcgid++) {
// Reset Buffer Info
mac->scheduling_info.lcg_sched_info[lcgid].BSR = 0;
mac->scheduling_info.lcg_sched_info[lcgid].BSR_bytes = 0;
}
bool bsr_regular_triggered = mac->scheduling_info.BSR_reporting_active & NR_BSR_TRIGGER_REGULAR;
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i];
int lcid = lc_info->lcid;
NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lcid);
int lcgid = lc_sched_info->LCGID;
// check if UL data for a logical channel which belongs to a LCG becomes available for transmission
if (lcgid != NR_INVALID_LCGID) {
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mac->ue_id,
mac->ue_id,
gNB_index,
frameP,
slotP,
ENB_FLAG_NO,
MBMS_FLAG_NO,
lcid,
0,
0);
lc_sched_info->LCID_buffer_remain = rlc_status.bytes_in_buffer;
mac_rlc_status_resp_t rlc_status =
mac_rlc_status_ind(mac->ue_id, mac->ue_id, gNB_index, frameP, slotP, ENB_FLAG_NO, MBMS_FLAG_NO, lcid, 0, 0);
if (rlc_status.bytes_in_buffer > 0) {
LOG_D(NR_MAC,
"[UE %d] LCID %d LCGID %d has %d bytes to transmit at frame %d slot %d\n",
"[UE %d] LCID %d has %d bytes to transmit at sfn %d.%d\n",
mac->ue_id,
lcid,
lcgid,
rlc_status.bytes_in_buffer,
frameP,
slotP);
lc_sched_info->LCID_buffer_remain = rlc_status.bytes_in_buffer;
}
}
}
/*TS 38.321
A BSR shall be triggered if any of the following events occur:
- UL data, for a logical channel which belongs to an LCG, becomes available to the MAC entity; and either
=> here we don't implement exactly the same, there is no direct relation with new data came in the UE since last BSR
- this UL data belongs to a logical channel with higher priority than the priority of any logical channel
containing available UL data which belong to any LCG; or
=> same, we don't know the last BSR content
- none of the logical channels which belong to an LCG contains any available UL data.
in which case the BSR is referred below to as 'Regular BSR';
- UL resources are allocated and number of padding bits is equal to or larger than the size of the Buffer Status
Report MAC CE plus its subheader, in which case the BSR is referred below to as 'Padding BSR';
lc_sched_info->LCID_buffer_with_data = true;
- retxBSR-Timer expires, and at least one of the logical channels which belong to an LCG contains UL data, in
which case the BSR is referred below to as 'Regular BSR';
//Update BSR_bytes
mac->scheduling_info.lcg_sched_info[lcgid].BSR_bytes += rlc_status.bytes_in_buffer;
- periodicBSR-Timer expires, in which case the BSR is referred below to as 'Periodic BSR'.
*/
static void nr_update_bsr(NR_UE_MAC_INST_t *mac, uint32_t *LCG_bytes)
{
bool bsr_regular_triggered = mac->scheduling_info.BSR_reporting_active & NR_BSR_TRIGGER_REGULAR;
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i];
int lcid = lc_info->lcid;
NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lcid);
int lcgid = lc_sched_info->LCGID;
// check if UL data for a logical channel which belongs to a LCG becomes available for transmission
if (lcgid != NR_INVALID_LCGID) {
// Update waiting bytes for this LCG
LCG_bytes[lcgid] += lc_sched_info->LCID_buffer_remain;
if (!bsr_regular_triggered) {
bsr_regular_triggered = true;
trigger_regular_bsr(mac, lcid, lc_info->sr_DelayTimerApplied);
LOG_D(NR_MAC,
"[UE %d] MAC BSR Triggered LCID %d LCGID %d data become available at %d.%d\n",
mac->ue_id,
lcid,
lcgid,
frameP,
slotP);
}
LOG_D(NR_MAC, "[UE %d] MAC BSR Triggered\n", mac->ue_id);
}
}
}
......@@ -1533,14 +1545,11 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
nr_ue_prach_scheduler(mac, frame_tx, slot_tx);
}
// Periodic SRS scheduling
if(mac->state == UE_CONNECTED)
bool BSRsent = false;
if (mac->state == UE_CONNECTED) {
nr_ue_periodic_srs_scheduling(mac, frame_tx, slot_tx);
// Call BSR procedure as described in Section 5.4.5 in 38.321
// Check whether BSR is triggered before scheduling ULSCH
if(mac->state == UE_CONNECTED)
nr_update_bsr(mac, frame_tx, slot_tx, gNB_index);
nr_update_rlc_buffers_status(mac, frame_tx, slot_tx, gNB_index);
}
// Schedule ULSCH only if the current frame and slot match those in ul_config_req
// AND if a UL grant (UL DCI or Msg3) has been received (as indicated by num_pdus)
......@@ -1555,21 +1564,22 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
while (ulcfg_pdu->pdu_type != FAPI_NR_END) {
uint8_t *ulsch_input_buffer = ulsch_input_buffer_array[number_of_pdus];
if (ulcfg_pdu->pdu_type == FAPI_NR_UL_CONFIG_TYPE_PUSCH) {
uint32_t TBS_bytes = ulcfg_pdu->pusch_config_pdu.pusch_data.tb_size;
nfapi_nr_ue_pusch_pdu_t *pdu = &ulcfg_pdu->pusch_config_pdu;
uint32_t TBS_bytes = pdu->pusch_data.tb_size;
LOG_D(NR_MAC,
"harq_id %d, new_data_indicator %d, TBS_bytes %d (ra_state %d)\n",
ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id,
ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator,
pdu->pusch_data.harq_process_id,
pdu->pusch_data.new_data_indicator,
TBS_bytes,
ra->ra_state);
ulcfg_pdu->pusch_config_pdu.tx_request_body.fapiTxPdu = NULL;
pdu->tx_request_body.fapiTxPdu = NULL;
if ((ra->ra_state == nrRA_WAIT_RAR || ra->ra_state == nrRA_WAIT_MSGB) && !ra->cfra) {
nr_get_Msg3_MsgA_PUSCH_payload(mac, ulsch_input_buffer, TBS_bytes);
for (int k = 0; k < TBS_bytes; k++) {
LOG_D(NR_MAC, "(%i): 0x%x\n", k, ulsch_input_buffer[k]);
}
ulcfg_pdu->pusch_config_pdu.tx_request_body.fapiTxPdu = ulsch_input_buffer;
ulcfg_pdu->pusch_config_pdu.tx_request_body.pdu_length = TBS_bytes;
pdu->tx_request_body.fapiTxPdu = ulsch_input_buffer;
pdu->tx_request_body.pdu_length = TBS_bytes;
number_of_pdus++;
} else {
if (ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator
......@@ -1580,23 +1590,23 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
return;
}
// Getting IP traffic to be transmitted
int tx_power = ulcfg_pdu->pusch_config_pdu.tx_power;
int tx_power = pdu->tx_power;
int P_CMAX = nr_get_Pcmax(mac->p_Max,
mac->nr_band,
mac->frame_type,
mac->frequency_range,
mac->current_UL_BWP->channel_bandwidth,
ulcfg_pdu->pusch_config_pdu.qam_mod_order,
pdu->qam_mod_order,
false,
mac->current_UL_BWP->scs,
mac->current_UL_BWP->BWPSize,
ulcfg_pdu->pusch_config_pdu.transform_precoding,
ulcfg_pdu->pusch_config_pdu.rb_size,
ulcfg_pdu->pusch_config_pdu.rb_start);
pdu->transform_precoding,
pdu->rb_size,
pdu->rb_start);
nr_ue_get_sdu(mac, cc_id, frame_tx, slot_tx, gNB_index, ulsch_input_buffer, TBS_bytes, tx_power, P_CMAX);
ulcfg_pdu->pusch_config_pdu.tx_request_body.fapiTxPdu = ulsch_input_buffer;
ulcfg_pdu->pusch_config_pdu.tx_request_body.pdu_length = TBS_bytes;
nr_ue_get_sdu(mac, cc_id, frame_tx, slot_tx, gNB_index, ulsch_input_buffer, TBS_bytes, tx_power, P_CMAX, &BSRsent);
pdu->tx_request_body.fapiTxPdu = ulsch_input_buffer;
pdu->tx_request_body.pdu_length = TBS_bytes;
number_of_pdus++;
// start or restart dataInactivityTimer if any MAC entity transmits a MAC SDU for DTCH logical channel,
// or DCCH logical channel
......@@ -1637,7 +1647,10 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
}
if(mac->state == UE_CONNECTED)
nr_update_sr(mac);
nr_update_sr(mac, BSRsent);
// Global variables implicit logic
// far away, BSR_reporting_active is set
mac->scheduling_info.BSR_reporting_active = NR_BSR_TRIGGER_NONE;
// update Bj for all active lcids before LCP procedure
if (mac->current_UL_BWP) {
......@@ -1668,22 +1681,15 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
static uint8_t nr_locate_BsrIndexByBufferSize(const uint32_t *table, int size, int value)
{
uint8_t ju, jm, jl;
int ascend;
//DevAssert(size > 0);
//DevAssert(size <= 256);
if (value == 0) {
return 0; //elseif (value > 150000) return 63;
}
jl = 0; // lower bound
ju = size - 1; // upper bound
ascend = (table[ju] >= table[jl]) ? 1 : 0; // determine the order of the the table: 1 if ascending order of table, 0 otherwise
int jl = 0; // lower bound
int ju = size - 1; // upper bound
bool ascend = table[ju] >= table[jl] ? 1 : 0; // determine the order of the the table: 1 if ascending order of table, 0 otherwise
while (ju - jl > 1) { //If we are not yet done,
jm = (ju + jl) >> 1; //compute a midpoint,
int jm = (ju + jl) / 2; // compute a midpoint,
if ((value >= table[jm]) == ascend) {
jl = jm; // replace the lower limit
} else {
......@@ -2979,95 +2985,68 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, sub_fra
}
typedef struct {
uint8_t bsr_len;
uint8_t bsr_ce_len;
uint8_t bsr_header_len;
uint8_t phr_len;
uint8_t phr_ce_len;
uint8_t phr_header_len;
uint16_t sdu_length_total;
NR_BSR_SHORT *bsr_s;
NR_BSR_LONG *bsr_l;
NR_BSR_SHORT *bsr_t;
NR_SINGLE_ENTRY_PHR_MAC_CE* phr;
//NR_POWER_HEADROOM_CMD *phr_pr;
int tot_mac_ce_len;
uint8_t total_mac_pdu_header_len;
uint sdu_length_total;
NR_SINGLE_ENTRY_PHR_MAC_CE phr;
type_bsr_t bsr;
uint8_t *pdu_end;
uint8_t *end_for_tailer;
uint8_t *cur_ptr;
uint num_sdus;
// int highest_priority = 16;
// variable used to store the lcid data status during lcp
bool lcids_data_status[NR_MAX_NUM_LCID];
uint32_t lcp_allocation_counter;
} NR_UE_MAC_CE_INFO;
/*
nr_ue_get_sdu_mac_ce_pre finds length in various mac_ce field
Need nothing from mac_ce_p:
Update the following in mac_ce_p:
bsr_len;
bsr_ce_len;
bsr_header_len;
phr_len; TBD
phr_ce_len; TBD
phr_header_len; TBD
*/
static int nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac,
static void nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac,
int CC_id,
frame_t frameP,
sub_frame_t subframe,
uint8_t gNB_index,
uint8_t *ulsch_buffer,
uint32_t buflen,
int16_t tx_power,
int16_t P_CMAX,
NR_UE_MAC_CE_INFO *mac_ce_p)
uint32_t *LCG_bytes,
NR_UE_MAC_CE_INFO *mac_ce_p,
int tx_power,
int P_CMAX)
{
int num_lcg_id_with_data = 0;
// Preparing the MAC CEs sub-PDUs and get the total size
mac_ce_p->bsr_header_len = 0;
int lcg_id = 0;
while (lcg_id != NR_INVALID_LCGID) {
if (mac->scheduling_info.lcg_sched_info[lcg_id].BSR_bytes) {
num_lcg_id_with_data++;
}
lcg_id++;
}
*mac_ce_p = (NR_UE_MAC_CE_INFO){.pdu_end = ulsch_buffer + buflen, .cur_ptr = ulsch_buffer};
memset(mac_ce_p->lcids_data_status, 1, NR_MAX_NUM_LCID);
// Compute BSR Length if Regular or Periodic BSR is triggered
// WARNING: if BSR long is computed, it may be changed to BSR short during or after multiplexing
// If we decide here to send BSR long, we may decide later to use BSR short
// if there remains less than 1 LCGROUP with data after Tx
int bsr_len = 0;
if (mac->scheduling_info.BSR_reporting_active) {
AssertFatal((mac->scheduling_info.BSR_reporting_active & NR_BSR_TRIGGER_PADDING) == 0,
"Inconsistent BSR Trigger=%d !\n",
mac->scheduling_info.BSR_reporting_active);
// count the active channels
int num_lcg_id_with_data = 0;
for (int i = 0; i < NR_MAX_NUM_LCGID; i++) {
if (LCG_bytes[i])
num_lcg_id_with_data++;
}
// A Regular or Periodic BSR can only be sent if TBS is sufficient
// as transmitting only a BSR is not allowed if UE has data to transmit
if (num_lcg_id_with_data <= 1) {
if (buflen >= (sizeof(NR_BSR_SHORT) + sizeof(NR_MAC_SUBHEADER_FIXED) + 1)) {
mac_ce_p->bsr_ce_len = sizeof(NR_BSR_SHORT); // 1 byte
mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_FIXED); // 1 byte
}
} else {
if (buflen >= (num_lcg_id_with_data + 1 + sizeof(NR_MAC_SUBHEADER_SHORT) + 1)) {
mac_ce_p->bsr_ce_len = num_lcg_id_with_data + 1; // variable size
mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_SHORT); // 2 bytes
}
}
int size_for_long = num_lcg_id_with_data + sizeof(NR_BSR_LONG) + sizeof(NR_MAC_SUBHEADER_SHORT);
int size_for_short = sizeof(NR_BSR_SHORT) + sizeof(NR_MAC_SUBHEADER_FIXED);
if (num_lcg_id_with_data > 1 && buflen >= size_for_long)
bsr_len = size_for_long;
else if ((num_lcg_id_with_data > 0 && buflen >= size_for_short)
|| mac->scheduling_info.BSR_reporting_active & NR_BSR_TRIGGER_PERIODIC)
bsr_len = size_for_short;
}
mac_ce_p->bsr_len = mac_ce_p->bsr_ce_len + mac_ce_p->bsr_header_len;
nr_phr_info_t *phr_info = &mac->scheduling_info.phr_info;
mac_ce_p->phr_header_len = 0;
mac_ce_p->phr_ce_len = 0;
if (phr_info->is_configured && phr_info->phr_reporting > 0) {
if (buflen >= (mac_ce_p->bsr_len + sizeof(NR_MAC_SUBHEADER_FIXED) + sizeof(NR_SINGLE_ENTRY_PHR_MAC_CE))) {
int needed = sizeof(NR_MAC_SUBHEADER_FIXED) + sizeof(NR_SINGLE_ENTRY_PHR_MAC_CE);
if (buflen >= bsr_len + needed) {
if (mac->scheduling_info.phr_info.phr_reporting) {
mac_ce_p->phr_header_len = sizeof(NR_MAC_SUBHEADER_FIXED);
mac_ce_p->phr_ce_len = sizeof(NR_SINGLE_ENTRY_PHR_MAC_CE);
nr_ue_fill_phr(mac, mac_ce_p->phr, P_CMAX, tx_power, frameP, subframe);
mac_ce_p->phr_len = needed;
nr_ue_fill_phr(mac, &mac_ce_p->phr, P_CMAX, tx_power, frameP, subframe);
}
}
}
mac_ce_p->phr_len = mac_ce_p->phr_header_len + mac_ce_p->phr_ce_len;
return (mac_ce_p->bsr_len + mac_ce_p->phr_len);
mac_ce_p->end_for_tailer = mac_ce_p->pdu_end - bsr_len - mac_ce_p->phr_len;
}
/*
......@@ -3075,14 +3054,11 @@ static int nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac,
Need the following from mac_ce_p:
bsr_ce_len
bsr_len
sdu_length_total
total_mac_pdu_header_len
Update the following in mac_ce_p:
bsr_ce_len
bsr_header_len
bsr_len
tot_mac_ce_len
total_mac_pdu_header_len
bsr_s
bsr_l
bsr_t
......@@ -3090,30 +3066,21 @@ static int nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac,
static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac,
frame_t frame,
slot_t slot,
uint8_t *ulsch_buffer,
uint32_t buflen,
NR_UE_MAC_CE_INFO *mac_ce_p)
NR_UE_MAC_CE_INFO *mac_ce_p,
uint32_t *LCG_bytes,
bool *BSRsent)
{
// Compute BSR Values and update Nb LCGID with data after multiplexing
uint32_t padding_len = 0;
int num_lcg_id_with_data = 0;
int lcg_id_bsr_trunc = 0;
int lcg_id_bsr_max = 0;
NR_UE_SCHEDULING_INFO *sched_info = &mac->scheduling_info;
for (int lcg_id = 0; lcg_id < NR_MAX_NUM_LCGID; lcg_id++) {
if (mac_ce_p->bsr_ce_len == sizeof(NR_BSR_SHORT)) {
sched_info->lcg_sched_info[lcg_id].BSR =
nr_locate_BsrIndexByBufferSize(NR_SHORT_BSR_TABLE,
NR_SHORT_BSR_TABLE_SIZE,
sched_info->lcg_sched_info[lcg_id].BSR_bytes);
} else {
sched_info->lcg_sched_info[lcg_id].BSR =
nr_locate_BsrIndexByBufferSize(NR_LONG_BSR_TABLE,
NR_LONG_BSR_TABLE_SIZE,
sched_info->lcg_sched_info[lcg_id].BSR_bytes);
}
if (sched_info->lcg_sched_info[lcg_id].BSR_bytes) {
num_lcg_id_with_data++;
lcg_id_bsr_trunc = lcg_id;
// Search the LCGID within waiting data for the highest priority LC
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
int lcid = mac->lc_ordered_list.array[i]->lcid;
NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid);
if (sched_info->LCID_buffer_remain) {
// this is the highest priority LC with data to transmit
lcg_id_bsr_max = sched_info->LCGID;
break;
}
}
......@@ -3128,119 +3095,79 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac,
- else report Short BSR.
- else if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR.
*/
if (mac_ce_p->sdu_length_total) {
padding_len = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total);
}
if ((padding_len) && (mac_ce_p->bsr_len == 0)) {
/* if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR */
if (padding_len >= (num_lcg_id_with_data + 1 + sizeof(NR_MAC_SUBHEADER_SHORT))) {
mac_ce_p->bsr_ce_len = num_lcg_id_with_data + 1; //variable size
mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_SHORT); //2 bytes
// Trigger BSR Padding
sched_info->BSR_reporting_active |= NR_BSR_TRIGGER_PADDING;
} else if (padding_len >= (sizeof(NR_BSR_SHORT)+sizeof(NR_MAC_SUBHEADER_FIXED))) {
mac_ce_p->bsr_ce_len = sizeof(NR_BSR_SHORT); //1 byte
mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_FIXED); //1 byte
if (num_lcg_id_with_data > 1) {
// REPORT SHORT TRUNCATED BSR
// Get LCGID of highest priority LCID with data (todo)
for (int lcid = 1; lcid <= NR_MAX_NUM_LCID; lcid++) {
NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid);
if ((sched_info->LCGID != NR_INVALID_LCGID) && (mac->scheduling_info.lcg_sched_info[sched_info->LCGID].BSR_bytes)) {
lcg_id_bsr_trunc = sched_info->LCGID;
}
}
} else {
// Report SHORT BSR, clear bsr_t
mac_ce_p->bsr_t = NULL;
}
// Trigger BSR Padding
sched_info->BSR_reporting_active |= NR_BSR_TRIGGER_PADDING;
}
mac_ce_p->bsr_len = mac_ce_p->bsr_header_len + mac_ce_p->bsr_ce_len;
mac_ce_p->tot_mac_ce_len += mac_ce_p->bsr_len;
mac_ce_p->total_mac_pdu_header_len += mac_ce_p->bsr_len;
}
//Fill BSR Infos
if (mac_ce_p->bsr_ce_len == 0) {
mac_ce_p->bsr_s = NULL;
mac_ce_p->bsr_l = NULL;
mac_ce_p->bsr_t = NULL;
} else if (mac_ce_p->bsr_header_len == sizeof(NR_MAC_SUBHEADER_SHORT)) {
mac_ce_p->bsr_s = NULL;
mac_ce_p->bsr_t = NULL;
mac_ce_p->bsr_l->Buffer_size0 = sched_info->lcg_sched_info[0].BSR;
mac_ce_p->bsr_l->Buffer_size1 = sched_info->lcg_sched_info[1].BSR;
mac_ce_p->bsr_l->Buffer_size2 = sched_info->lcg_sched_info[2].BSR;
mac_ce_p->bsr_l->Buffer_size3 = sched_info->lcg_sched_info[3].BSR;
mac_ce_p->bsr_l->Buffer_size4 = sched_info->lcg_sched_info[4].BSR;
mac_ce_p->bsr_l->Buffer_size5 = sched_info->lcg_sched_info[5].BSR;
mac_ce_p->bsr_l->Buffer_size6 = sched_info->lcg_sched_info[6].BSR;
mac_ce_p->bsr_l->Buffer_size7 = sched_info->lcg_sched_info[7].BSR;
LOG_D(NR_MAC,
"[UE %d] Frame %d subframe %d BSR Trig=%d report LONG BSR (level LCGID0 %d,level LCGID1 %d,level LCGID2 %d,level LCGID3 "
"%d level LCGID4 %d,level LCGID5 %d,level LCGID6 %d,level LCGID7 %d)\n",
mac->ue_id,
frame,
slot,
sched_info->BSR_reporting_active,
sched_info->lcg_sched_info[0].BSR,
sched_info->lcg_sched_info[1].BSR,
sched_info->lcg_sched_info[2].BSR,
sched_info->lcg_sched_info[3].BSR,
sched_info->lcg_sched_info[4].BSR,
sched_info->lcg_sched_info[5].BSR,
sched_info->lcg_sched_info[6].BSR,
sched_info->lcg_sched_info[7].BSR);
} else if (mac_ce_p->bsr_header_len == sizeof(NR_MAC_SUBHEADER_FIXED)) {
mac_ce_p->bsr_l = NULL;
if ((mac_ce_p->bsr_t != NULL) && (sched_info->BSR_reporting_active & NR_BSR_TRIGGER_PADDING)) {
//Truncated BSR
mac_ce_p->bsr_s = NULL;
mac_ce_p->bsr_t->LcgID = lcg_id_bsr_trunc;
mac_ce_p->bsr_t->Buffer_size = sched_info->lcg_sched_info[lcg_id_bsr_trunc].BSR;
uint32_t padding_len = mac_ce_p->pdu_end - mac_ce_p->cur_ptr - mac_ce_p->phr_len;
AssertFatal(padding_len >= 0, "Error in buffer size compute");
mac_ce_p->bsr.type_bsr = b_none;
int short_bsr_sz = sizeof(NR_BSR_SHORT) + sizeof(NR_MAC_SUBHEADER_FIXED);
int num_lcg_id_with_data = 0;
for (int lcg_id = 0; lcg_id < NR_MAX_NUM_LCGID; lcg_id++)
num_lcg_id_with_data += LCG_bytes > 0;
int long_bsr_sz = num_lcg_id_with_data + sizeof(NR_BSR_LONG) + sizeof(NR_MAC_SUBHEADER_SHORT);
if (num_lcg_id_with_data < 2 && padding_len >= short_bsr_sz) {
mac_ce_p->bsr.type_bsr = b_short;
mac_ce_p->bsr.bsr.s.LcgID = lcg_id_bsr_max;
mac_ce_p->bsr.bsr.s.Buffer_size =
nr_locate_BsrIndexByBufferSize(NR_SHORT_BSR_TABLE, NR_SHORT_BSR_TABLE_SIZE, LCG_bytes[lcg_id_bsr_max]);
LOG_D(NR_MAC,
"[UE %d] Frame %d subframe %d BSR Trig=%d report TRUNCATED BSR with level %d for LCGID %d\n",
"[UE %d] sfn %d.%d BSR Trigger=0x%x report SHORT BSR with level %d for LCGID %d\n",
mac->ue_id,
frame,
slot,
sched_info->BSR_reporting_active,
sched_info->lcg_sched_info[lcg_id_bsr_trunc].BSR,
lcg_id_bsr_trunc);
} else {
mac_ce_p->bsr_t = NULL;
mac_ce_p->bsr_s->LcgID = lcg_id_bsr_trunc;
mac_ce_p->bsr_s->Buffer_size = sched_info->lcg_sched_info[lcg_id_bsr_trunc].BSR;
mac_ce_p->bsr.bsr.s.Buffer_size,
lcg_id_bsr_max);
} else if (padding_len >= long_bsr_sz) {
/* if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader,
report Long BSR whatever periodic or regular BSR*/
mac_ce_p->bsr.type_bsr = b_long;
uint8_t *tmp = mac_ce_p->bsr.bsr.lcg_bsr;
for (int lcg_id = 0; lcg_id < 8; lcg_id++) {
tmp[lcg_id] = nr_locate_BsrIndexByBufferSize(NR_LONG_BSR_TABLE, NR_LONG_BSR_TABLE_SIZE, LCG_bytes[lcg_id]);
}
LOG_D(NR_MAC,
"[UE %d] Frame %d subframe %d BSR Trig=%d report SHORT BSR with level %d for LCGID %d\n",
"[UE %d] sfn %d.%d BSR Trig=0x%x report LONG BSR (level LCGID %d %d %d %d %d %d %d %d)\n",
mac->ue_id,
frame,
slot,
sched_info->BSR_reporting_active,
sched_info->lcg_sched_info[lcg_id_bsr_trunc].BSR,
lcg_id_bsr_trunc);
}
tmp[0],
tmp[1],
tmp[2],
tmp[3],
tmp[4],
tmp[5],
tmp[6],
tmp[7]);
} else if (padding_len == short_bsr_sz) {
mac_ce_p->bsr.type_bsr = b_short_trunc;
mac_ce_p->bsr.bsr.s.LcgID = lcg_id_bsr_max;
mac_ce_p->bsr.bsr.s.Buffer_size =
nr_locate_BsrIndexByBufferSize(NR_SHORT_BSR_TABLE, NR_SHORT_BSR_TABLE_SIZE, LCG_bytes[lcg_id_bsr_max]);
} else if (padding_len >= sizeof(NR_BSR_LONG) + sizeof(NR_MAC_SUBHEADER_SHORT)) {
mac_ce_p->bsr.type_bsr = b_long_trunc;
// Fixme: this should be sorted by (TS 38.321, 5.4.5)
// the logical channels having data available for
// transmission following a decreasing order of the highest priority logical channel (with or without data
// available for transmission) in each of these LCG(s), and in case of equal priority, in increasing order of LCGID
uint8_t *tmp = mac_ce_p->bsr.bsr.lcg_bsr;
for (int lcg_id = 0; lcg_id < 8; lcg_id++) {
tmp[lcg_id] = nr_locate_BsrIndexByBufferSize(NR_LONG_BSR_TABLE, NR_LONG_BSR_TABLE_SIZE, LCG_bytes[lcg_id]);
}
} else
LOG_D(NR_MAC, "Can't add any BSR, not enough padding\n");
/* Actions when a BSR is sent */
if (mac_ce_p->bsr_ce_len) {
if (mac_ce_p->bsr.type_bsr != b_none) {
LOG_D(NR_MAC,
"[UE %d] MAC BSR Sent! ce %d, hdr %d buff_len %d triggering LCID %ld\n",
"[UE %d] MAC BSR Sent! buff_len %ld triggering LCID %ld\n",
mac->ue_id,
mac_ce_p->bsr_ce_len,
mac_ce_p->bsr_header_len,
buflen,
mac_ce_p->pdu_end - mac_ce_p->cur_ptr,
sched_info->regularBSR_trigger_lcid);
*BSRsent = true;
// Reset ReTx BSR Timer
nr_timer_start(&sched_info->retxBSR_Timer);
// Reset Periodic Timer except when BSR is truncated
if (mac_ce_p->bsr_t == NULL) {
if (mac_ce_p->bsr.type_bsr != b_long_trunc && mac_ce_p->bsr.type_bsr != b_short_trunc) {
nr_timer_start(&sched_info->periodicBSR_Timer);
LOG_D(NR_MAC, "[UE %d] MAC Periodic BSR Timer Reset\n", mac->ue_id);
}
......@@ -3256,10 +3183,12 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac,
nr_timer_stop(&sr->prohibitTimer);
}
}
// Reset BSR Trigger flags
sched_info->BSR_reporting_active = NR_BSR_TRIGGER_NONE;
sched_info->regularBSR_trigger_lcid = 0;
}
int size =
nr_write_ce_ulsch_pdu(mac_ce_p->cur_ptr, mac, mac_ce_p->phr_len ? &mac_ce_p->phr : NULL, &mac_ce_p->bsr, mac_ce_p->pdu_end);
LOG_D(NR_MAC, "Added %d bytes of BSR\n", size);
mac_ce_p->cur_ptr += size;
}
uint32_t get_count_lcids_same_priority(uint8_t start, uint8_t total_active_lcids, nr_lcordered_info_t *lcid_ordered_array)
......@@ -3276,7 +3205,7 @@ uint32_t get_count_lcids_same_priority(uint8_t start, uint8_t total_active_lcids
return same_priority_count;
}
long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac,
static long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac,
uint8_t same_priority_count,
uint8_t lc_num,
uint32_t buflen_remain_ep,
......@@ -3288,7 +3217,7 @@ long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac,
/* Calculates the number of bytes the logical channel should request from the correcponding RLC buffer*/
nr_lcordered_info_t *lc_info = get_lc_info_from_lcid(mac, lc_num);
AssertFatal(lc_info, "Couldn't find logical channel with LCID %d\n", lc_num);
uint32_t pbr = lc_info->pbr;
const uint32_t pbr = lc_info->pbr;
NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lc_num);
int32_t lcid_remain_buffer = sched_info->LCID_buffer_remain;
*target = (same_priority_count > 1) ? min(buflen_remain_ep, pbr) : pbr;
......@@ -3309,7 +3238,8 @@ long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac,
num_bytes_requested = min(buflen_remain, lcid_remain_buffer);
}
}
AssertFatal(num_remaining_bytes >= 0, "the total number of bytes allocated until target length is greater than expected\n");
AssertFatal(num_remaining_bytes >= 0 && num_bytes_requested <= buflen_remain,
"the total number of bytes allocated until target length is greater than expected\n");
LOG_D(NR_MAC, "number of bytes requested for lcid %d is %li\n", lc_num, num_bytes_requested);
return num_bytes_requested;
......@@ -3327,64 +3257,69 @@ bool get_dataavailability_buffers(uint8_t total_active_lcids, nr_lcordered_info_
return false;
}
static void select_logical_channels(NR_UE_MAC_INST_t *mac, int *num_active_lcids, nr_lcordered_info_t *active_lcids)
static uint select_logical_channels(NR_UE_MAC_INST_t *mac, nr_lcordered_info_t *active_lcids)
{
// (TODO: selection of logical channels for logical channel prioritization procedure as per 5.4.3.1.2 Selection of logical
// channels, TS38.321)
int nb = 0;
// selection of logical channels with Bj > 0
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
int lcid = mac->lc_ordered_list.array[i]->lcid;
NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid);
if (sched_info->Bj > 0) {
active_lcids[*num_active_lcids] = *mac->lc_ordered_list.array[i];
(*num_active_lcids)++;
LOG_D(NR_MAC, "The available lcid is %d with total active channels count = %d\n", lcid, *num_active_lcids);
active_lcids[nb++] = *mac->lc_ordered_list.array[i];
LOG_D(NR_MAC, "The available lcid is %d with total active channels count = %d\n", lcid, nb);
}
}
return nb;
}
static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac,
frame_t frame,
slot_t slot,
uint8_t gNB_index,
uint32_t buflen,
int32_t *buflen_remain,
int lcid,
uint8_t **pdu,
uint32_t *counter,
uint8_t count_same_priority_lcids,
uint count_same_priority_lcids,
uint32_t buflen_ep,
uint32_t *lcids_bytes_tot,
uint16_t *num_sdus,
NR_UE_MAC_CE_INFO *mac_ce_p,
bool *lcids_data_status,
uint8_t *num_lcids_same_priority)
uint *num_lcids_same_priority,
uint32_t *LCG_bytes)
{
const uint8_t sh_size = sizeof(NR_MAC_SUBHEADER_LONG);
/* prepare the MAC sdu */
NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid);
int32_t lcid_remain_buffer = sched_info->LCID_buffer_remain;
uint usable = mac_ce_p->end_for_tailer - mac_ce_p->cur_ptr;
LOG_D(NR_MAC,
"[UE %d] [%d.%d] lcp round = %d, remaining mac pdu length = %d, lcid buffer remaining = %d, lcid = %d \n",
"[UE %d] [%d.%d] lcp round = %d, remaining mac pdu length before BSR = %d, lcid buffer remaining = %d, lcid = %d \n",
mac->ue_id,
frame,
slot,
*counter,
*buflen_remain,
mac_ce_p->lcp_allocation_counter,
usable,
lcid_remain_buffer,
lcid);
// 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);
if (mac_ce_p->end_for_tailer - mac_ce_p->cur_ptr < sizeof(NR_MAC_SUBHEADER_LONG))
// We can't add one byte after the header
return false;
*pdu += sh_size;
// 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 *)mac_ce_p->cur_ptr;
// number of bytes requested from RLC for each LCID
long target = 0;
long bytes_requested =
get_num_bytes_to_reqlc(mac, count_same_priority_lcids, lcid, buflen_ep, *buflen_remain, *counter, lcids_bytes_tot, &target);
// NR_MAC_SUBHEADER_SHORT can handle up to 256 bytes message
int header_sz = usable < 256 ? sizeof(NR_MAC_SUBHEADER_SHORT) : sizeof(NR_MAC_SUBHEADER_LONG);
long bytes_requested = get_num_bytes_to_reqlc(mac,
count_same_priority_lcids,
lcid,
buflen_ep,
usable - header_sz,
mac_ce_p->lcp_allocation_counter,
lcids_bytes_tot,
&target);
header_sz = bytes_requested < 256 ? sizeof(NR_MAC_SUBHEADER_SHORT) : sizeof(NR_MAC_SUBHEADER_LONG);
uint16_t sdu_length = mac_rlc_data_req(mac->ue_id,
mac->ue_id,
......@@ -3394,7 +3329,7 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac,
MBMS_FLAG_NO,
lcid,
bytes_requested,
(char *)(*pdu),
(char *)mac_ce_p->cur_ptr + header_sz,
0,
0);
......@@ -3418,62 +3353,49 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac,
int lc_idx = lcid_buffer_index(lcid);
if (sdu_length > 0) {
mac_ce_p->num_sdus++;
LOG_D(NR_MAC,
"[UE %d] [%d.%d] UL-DXCH -> ULSCH, Generating UL MAC sub-PDU for SDU %d, length %d bytes, RB with LCID "
"0x%02x (buflen (TBS) %d bytes)\n",
"0x%02x (buflen (TBS) %ld bytes)\n",
mac->ue_id,
frame,
slot,
(*num_sdus) + 1,
mac_ce_p->num_sdus,
sdu_length,
lcid,
buflen);
header->R = 0;
header->F = 1;
header->LCID = lcid;
header->L = htons(sdu_length);
mac_ce_p->end_for_tailer - mac_ce_p->cur_ptr);
if (header_sz == sizeof(NR_MAC_SUBHEADER_SHORT)) {
*(NR_MAC_SUBHEADER_SHORT *)header = (NR_MAC_SUBHEADER_SHORT){.R = 0, .F = 0, .LCID = lcid, .L = sdu_length};
} else {
*header = (NR_MAC_SUBHEADER_LONG){.R = 0, .F = 1, .LCID = lcid, .L = htons(sdu_length)};
#ifdef ENABLE_MAC_PAYLOAD_DEBUG
LOG_I(NR_MAC, "dumping MAC sub-header with length %d: \n", sh_size);
log_dump(NR_MAC, header, sh_size, LOG_DUMP_CHAR, "\n");
LOG_I(NR_MAC, "dumping MAC SDU with length %d \n", sdu_length);
log_dump(NR_MAC, *pdu, sdu_length, LOG_DUMP_CHAR, "\n");
LOG_I(NR_MAC, "dumping MAC SDU with length %d: \n", sduL);
log_dump(NR_MAC, header, sduL, LOG_DUMP_CHAR, "\n");
#endif
*pdu += sdu_length;
mac_ce_p->sdu_length_total += sdu_length;
mac_ce_p->total_mac_pdu_header_len += sh_size;
(*num_sdus)++;
}
mac_ce_p->cur_ptr += header_sz + sdu_length;
} else {
*pdu -= sh_size;
lcids_data_status[lc_idx] = false;
mac_ce_p->lcids_data_status[lc_idx] = false;
(*num_lcids_same_priority)--;
LOG_D(NR_MAC, "No data to transmit for RB with LCID 0x%02x and hence set to false\n", lcid);
return 0;
LOG_D(NR_MAC, "No data to transmit for RB with LCID 0x%02x\n and hence set to false", lcid);
return false;
}
*buflen_remain = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total + sh_size);
// Update Buffer remain and BSR bytes after transmission
NR_LCG_SCHEDULING_INFO *lcg_info = &mac->scheduling_info.lcg_sched_info[0];
sched_info->LCID_buffer_remain -= sdu_length;
(lcg_info + sched_info->LCGID)->BSR_bytes -= sdu_length;
LCG_bytes[sched_info->LCGID] -= sdu_length;
LOG_D(NR_MAC,
"[UE %d] Update BSR [%d.%d] BSR_bytes for LCG%ld = %d\n",
"[UE %d] Update BSR [%d.%d] LCG_bytes for LCG%ld = %d\n",
mac->ue_id,
frame,
slot,
sched_info->LCGID,
(lcg_info + sched_info->LCGID)->BSR_bytes);
if ((lcg_info + sched_info->LCGID)->BSR_bytes < 0)
(lcg_info + sched_info->LCGID)->BSR_bytes = 0;
LCG_bytes[sched_info->LCGID]);
// update number of bytes served from the current lcid
lcids_bytes_tot[lc_idx] += (sdu_length + (count_same_priority_lcids > 1 ? 1 : 0) * sh_size);
lcids_bytes_tot[lc_idx] += (sdu_length + (count_same_priority_lcids > 1 ? 1 : 0) * sizeof(NR_MAC_SUBHEADER_LONG));
if ((*counter == 0 && lcids_bytes_tot[lc_idx] >= target)
if ((mac_ce_p->lcp_allocation_counter == 0 && lcids_bytes_tot[lc_idx] >= target)
|| (count_same_priority_lcids > 1
&& lcids_bytes_tot[lc_idx] >= buflen_ep)) { // only prioritized bit rate should be taken from logical channel in
// the first lcp run except when infinity
......@@ -3482,9 +3404,9 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac,
lcid,
lcids_bytes_tot[lc_idx]);
(*num_lcids_same_priority)--;
return 0;
return false;
}
return 1;
return true;
}
/**
......@@ -3499,77 +3421,55 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac,
* @ulsch_buffer Pointer to ULSCH PDU
* @buflen TBS
*/
uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
int CC_id,
frame_t frame,
slot_t slot,
uint8_t gNB_index,
uint8_t *ulsch_buffer,
uint32_t buflen,
int16_t tx_power,
int16_t P_CMAX)
const uint32_t buflen,
int tx_power,
int P_CMAX,
bool *BSRsent)
{
NR_UE_MAC_CE_INFO mac_ce_info;
NR_UE_MAC_CE_INFO *mac_ce_p=&mac_ce_info;
int32_t buflen_remain = 0;
mac_ce_p->bsr_len = 0;
mac_ce_p->bsr_ce_len = 0;
mac_ce_p->bsr_header_len = 0;
mac_ce_p->phr_len = 0;
//mac_ce_p->phr_ce_len = 0;
//mac_ce_p->phr_header_len = 0;
uint16_t num_sdus = 0;
mac_ce_p->sdu_length_total = 0;
NR_BSR_SHORT bsr_short, bsr_truncated;
NR_BSR_LONG bsr_long;
mac_ce_p->bsr_s = &bsr_short;
mac_ce_p->bsr_l = &bsr_long;
mac_ce_p->bsr_t = &bsr_truncated;
NR_SINGLE_ENTRY_PHR_MAC_CE phr;
mac_ce_p->phr = &phr;
//int highest_priority = 16;
const 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;
// variable used to store the lcid data status during lcp
bool lcids_data_status[NR_MAX_NUM_LCID] = {0};
memset(lcids_data_status, 1, NR_MAX_NUM_LCID);
// in the first run all the lc are allocated as per bj and prioritized bit rate but in subsequent runs, no need to consider
uint32_t lcp_allocation_counter = 0;
// bj and prioritized bit rate but just consider priority
uint32_t buflen_ep = 0; // this variable holds the length in bytes in mac pdu when multiple equal priority channels are present
// because as per standard(TS38.321), all equal priority channels should be served equally
// nr_ue_get_sdu_mac_ce_pre updates all mac_ce related header field related to length
mac_ce_p->tot_mac_ce_len = nr_ue_get_sdu_mac_ce_pre(mac, CC_id, frame, slot, gNB_index, ulsch_buffer, buflen, tx_power, P_CMAX, mac_ce_p);
mac_ce_p->total_mac_pdu_header_len = mac_ce_p->tot_mac_ce_len;
// Call BSR procedure as described in Section 5.4.5 in 38.321
// Check whether BSR is triggered before scheduling ULSCH
uint32_t LCG_bytes[NR_MAX_NUM_LCGID] = {0};
nr_update_bsr(mac, LCG_bytes);
LOG_D(NR_MAC, "[UE %d] [%d.%d] process UL transport block at with size TBS = %d bytes \n", mac->ue_id, frame, slot, buflen);
nr_ue_get_sdu_mac_ce_pre(mac, CC_id, frame, slot, gNB_index, ulsch_buffer, buflen, LCG_bytes, &mac_ce_info, tx_power, P_CMAX);
LOG_D(NR_MAC,
"[UE %d] [%d.%d] process UL transport block with size TBS = %d bytes, number of existing LCids %d \n",
mac->ue_id,
frame,
slot,
buflen,
mac->lc_ordered_list.count);
// selection of logical channels
int avail_lcids_count = 0;
// variable used to build the lcids with positive Bj
nr_lcordered_info_t lcids_bj_pos[mac->lc_ordered_list.count];
select_logical_channels(mac, &avail_lcids_count, lcids_bj_pos);
int avail_lcids_count = select_logical_channels(mac, lcids_bj_pos);
// multiplex in the order of highest priority
do {
/*
go until there is space availabile in the MAC PDU and there is data available in RLC buffers of active logical channels
*/
uint8_t num_lcids_same_priority = 0;
uint8_t count_same_priority_lcids = 0;
uint num_lcids_same_priority = 0;
uint count_same_priority_lcids = 0;
// variable used to store the total bytes read from rlc for each lcid
uint32_t lcids_bytes_tot[NR_MAX_NUM_LCID] = {0};
for (uint8_t id = 0; id < avail_lcids_count; id++) {
for (uint id = 0; id < avail_lcids_count; id++) {
/*
loop over all logical channels in the order of priority. As stated in TS138.321 Section 5.4.3.1, in the first run, only
prioritized number of bytes are taken out from the corresponding RLC buffers of all active logical channels and if there is
......@@ -3577,45 +3477,36 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
is placed in the MAC PDU before going on to next high priority logical channel
*/
int lcid = lcids_bj_pos[id].lcid;
NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lcid);
int idx = lcid_buffer_index(lcid);
// skip the logical channel if no data in the buffer initially or the data in the buffer was zero because it was written in to
// MAC PDU
if (!lc_sched_info->LCID_buffer_with_data || !lcids_data_status[idx]) {
lcids_data_status[idx] = false;
if (!mac_ce_info.lcids_data_status[idx]) {
continue;
}
// count number of lc with same priority as lcid
if (!num_lcids_same_priority) {
num_lcids_same_priority = count_same_priority_lcids =
get_count_lcids_same_priority(id, avail_lcids_count, lcids_bj_pos);
num_lcids_same_priority = count_same_priority_lcids = get_count_lcids_same_priority(id, avail_lcids_count, lcids_bj_pos);
}
buflen_remain = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total + sh_size);
int remain = mac_ce_info.end_for_tailer - mac_ce_info.cur_ptr;
LOG_D(NR_MAC,
"[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",
"[UE %d] [%d.%d] UL-DXCH -> ULSCH, RLC with LCID 0x%02x buflen_remain %d bytes)\n",
mac->ue_id,
frame,
slot,
lcid,
buflen,
mac_ce_p->sdu_length_total,
mac_ce_p->tot_mac_ce_len,
buflen_remain);
remain);
if (num_lcids_same_priority == count_same_priority_lcids) {
const int32_t buflen_ep_tmp = (buflen_remain - (count_same_priority_lcids * sh_size)) / count_same_priority_lcids;
buflen_ep = (remain - (count_same_priority_lcids * sizeof(NR_MAC_SUBHEADER_LONG))) / count_same_priority_lcids;
/* after serving equal priority LCIDs in the first round, buflen_remain could be > 0 and < (count_same_priority_lcids * sh_size)
if above division yeilds a remainder. hence the following sets buflen_ep to 0 if there is not enough buffer left for subsequent rounds
*/
buflen_ep = buflen_ep_tmp < 0 ? 0 : buflen_ep_tmp;
buflen_ep = buflen_ep < 0 ? 0 : buflen_ep;
}
while (buflen_remain > 0) {
while (mac_ce_info.end_for_tailer - mac_ce_info.cur_ptr > 0) {
/*
loops until the requested number of bytes from MAC to RLC are placed in the MAC PDU. The number of requested bytes
depends on whether it is the first run or otherwise because in the first run only prioritited number of bytes of all
......@@ -3626,80 +3517,38 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
frame,
slot,
gNB_index,
buflen,
&buflen_remain,
lcid,
&pdu,
&lcp_allocation_counter,
count_same_priority_lcids,
buflen_ep,
lcids_bytes_tot,
&num_sdus,
mac_ce_p,
lcids_data_status,
&num_lcids_same_priority)) {
&mac_ce_info,
&num_lcids_same_priority,
LCG_bytes)) {
break;
}
}
}
lcp_allocation_counter++;
} while (buflen_remain > 0 && get_dataavailability_buffers(avail_lcids_count, lcids_bj_pos, lcids_data_status));
mac_ce_info.lcp_allocation_counter++;
} while (mac_ce_info.end_for_tailer - mac_ce_info.cur_ptr > sizeof(NR_MAC_SUBHEADER_LONG)
&& get_dataavailability_buffers(avail_lcids_count, lcids_bj_pos, mac_ce_info.lcids_data_status));
//nr_ue_get_sdu_mac_ce_post recalculates all mac_ce related header fields since buffer has been changed after mac_rlc_data_req.
//Also, BSR padding is handled here after knowing mac_ce_p->sdu_length_total.
nr_ue_get_sdu_mac_ce_post(mac, frame, slot, ulsch_buffer, buflen, mac_ce_p);
if (mac_ce_p->tot_mac_ce_len > 0) {
LOG_D(NR_MAC, "In %s copying %d bytes of MAC CEs to the UL PDU \n", __FUNCTION__, mac_ce_p->tot_mac_ce_len);
int size = nr_write_ce_ulsch_pdu(pdu, mac, mac_ce_p->phr_ce_len ? mac_ce_p->phr : NULL, 0, mac_ce_p->bsr_t, mac_ce_p->bsr_s, mac_ce_p->bsr_l);
if (size != mac_ce_p->tot_mac_ce_len)
LOG_E(NR_MAC, "MAC CE size computed by nr_write_ce_ulsch_pdu is %d while the one assumed before is %d\n", size, mac_ce_p->tot_mac_ce_len);
pdu += (unsigned char) mac_ce_p->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__, mac_ce_p->tot_mac_ce_len);
log_dump(NR_MAC, mac_header_control_elements, mac_ce_p->tot_mac_ce_len, LOG_DUMP_CHAR, "\n");
#endif
}
buflen_remain = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total);
nr_ue_get_sdu_mac_ce_post(mac, frame, slot, &mac_ce_info, LCG_bytes, BSRsent);
// Compute final offset for padding and fill remainder of ULSCH with 0
if (buflen_remain > 0) {
LOG_D(NR_MAC, "Filling remainder %d bytes to the UL PDU \n", buflen_remain);
((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, "Padding MAC sub-header with length %ld bytes \n", sizeof(NR_MAC_SUBHEADER_FIXED));
log_dump(NR_MAC, pdu, sizeof(NR_MAC_SUBHEADER_FIXED), LOG_DUMP_CHAR, "\n");
#endif
pdu++;
buflen_remain--;
if (IS_SOFTMODEM_RFSIM) {
for (int j = 0; j < buflen_remain; j++) {
pdu[j] = (unsigned char)rand();
}
} else {
memset(pdu, 0, buflen_remain);
int remain = mac_ce_info.pdu_end - mac_ce_info.cur_ptr;
if (remain) {
LOG_D(NR_MAC, "Filling remainder %d bytes to the UL PDU \n", remain);
*(NR_MAC_SUBHEADER_FIXED *)mac_ce_info.cur_ptr = (NR_MAC_SUBHEADER_FIXED){.R = 0, .LCID = UL_SCH_LCID_PADDING};
mac_ce_info.cur_ptr++;
memset(mac_ce_info.cur_ptr, 0, mac_ce_info.pdu_end - mac_ce_info.cur_ptr);
}
#ifdef ENABLE_MAC_PAYLOAD_DEBUG
LOG_I(NR_MAC, "MAC padding sub-PDU with length %d bytes \n", buflen_remain);
log_dump(NR_MAC, pdu, buflen_remain, LOG_DUMP_CHAR, "\n");
#endif
}
#ifdef ENABLE_MAC_PAYLOAD_DEBUG
LOG_I(NR_MAC, "Dumping MAC PDU with length %d: \n", buflen);
LOG_I(NR_MAC, "MAC PDU %d bytes \n", mac_ce_p->cur_ptr - ulsch_buffer);
log_dump(NR_MAC, ulsch_buffer, buflen, LOG_DUMP_CHAR, "\n");
#endif
return num_sdus > 0 ? 1 : 0;
return mac_ce_info.num_sdus > 0; // success if we got at least one sdu
}
static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MAC_INST_t *mac)
......@@ -3726,7 +3575,7 @@ static void nr_ue_fill_phr(NR_UE_MAC_INST_t *mac,
nr_phr_info_t *phr_info = &mac->scheduling_info.phr_info;
// Value mapping according to 38.133 10.1.18.1
const int PC_MAX_00 = -29;
phr->PCMAX = max(0, (int)P_CMAX - PC_MAX_00) & 0x3f;
*phr = (NR_SINGLE_ENTRY_PHR_MAC_CE){.PCMAX = max(0, (int)P_CMAX - PC_MAX_00) & 0x3f};
// Value mapping according to 38.133 10.1.17.1.1
const int POWER_HEADROOM_55 = 22;
int headroom = P_CMAX - tx_power;
......
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