Commit 2ba79f3f authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/NR_UE_MAC_SR_improvements' into integration_2024_w15

parents 87242ca9 2f9fe364
......@@ -755,6 +755,7 @@ static void nr_configure_lc_config(NR_UE_MAC_INST_t *mac,
AssertFatal(mac_lc_config->ul_SpecificParameters, "UL parameters shouldn't be NULL for DRBs\n");
struct NR_LogicalChannelConfig__ul_SpecificParameters *ul_parm = mac_lc_config->ul_SpecificParameters;
lc_info->priority = ul_parm->priority;
lc_info->sr_id = ul_parm->schedulingRequestID ? *ul_parm->schedulingRequestID : -1;
lc_info->sr_DelayTimerApplied = ul_parm->logicalChannelSR_DelayTimerApplied;
lc_info->lc_SRMask = ul_parm->logicalChannelSR_Mask;
lc_info->pbr = nr_get_pbr(ul_parm->prioritisedBitRate);
......@@ -1691,37 +1692,35 @@ static uint32_t nr_get_sf_periodicBSRTimer(long periodicBSR)
static void configure_maccellgroup(NR_UE_MAC_INST_t *mac, const NR_MAC_CellGroupConfig_t *mcg)
{
NR_UE_SCHEDULING_INFO *si = &mac->scheduling_info;
int scs = mac->current_UL_BWP->scs;
if (mcg->drx_Config)
LOG_E(NR_MAC, "DRX not implemented! Configuration not handled!\n");
if (mcg->schedulingRequestConfig) {
const NR_SchedulingRequestConfig_t *src = mcg->schedulingRequestConfig;
if (src->schedulingRequestToReleaseList) {
for (int i = 0; i < src->schedulingRequestToReleaseList->list.count; i++) {
if (*src->schedulingRequestToReleaseList->list.array[i] == si->sr_id) {
si->SR_COUNTER = 0;
si->sr_ProhibitTimer = 0;
si->sr_ProhibitTimer_Running = 0;
si->sr_id = -1; // invalid init value
}
else
LOG_E(NR_MAC, "Cannot release SchedulingRequestConfig. Not configured.\n");
NR_SchedulingRequestId_t id = *src->schedulingRequestToReleaseList->list.array[i];
memset(&si->sr_info[id], 0, sizeof(si->sr_info[id]));
}
}
if (src->schedulingRequestToAddModList) {
for (int i = 0; i < src->schedulingRequestToAddModList->list.count; i++) {
NR_SchedulingRequestToAddMod_t *sr = src->schedulingRequestToAddModList->list.array[i];
AssertFatal(si->sr_id == -1 ||
si->sr_id == sr->schedulingRequestId,
"Current implementation cannot handle more than 1 SR configuration\n");
si->sr_id = sr->schedulingRequestId;
si->sr_TransMax = sr->sr_TransMax;
nr_sr_info_t *sr_info = &si->sr_info[sr->schedulingRequestId];
sr_info->active_SR_ID = true;
// NR_SchedulingRequestToAddMod__sr_TransMax_n4 = 0 and so on
// to obtain the value to configure we need to right shift 4 by the RRC parameter
sr_info->maxTransmissions = 4 << sr->sr_TransMax;
int target_ms = 0;
if (sr->sr_ProhibitTimer)
LOG_E(NR_MAC, "SR prohibit timer not properly implemented\n");
target_ms = 1 << *sr->sr_ProhibitTimer;
// length of slot is (1/2^scs)ms
nr_timer_setup(&sr_info->prohibitTimer, target_ms << scs, 1); // 1 slot update rate
}
}
}
if (mcg->bsr_Config) {
int subframes_per_slot = nr_slots_per_frame[mac->current_UL_BWP->scs] / 10;
int subframes_per_slot = nr_slots_per_frame[scs] / 10;
uint32_t periodic_sf = nr_get_sf_periodicBSRTimer(mcg->bsr_Config->periodicBSR_Timer);
uint32_t target = periodic_sf < UINT_MAX ? periodic_sf * subframes_per_slot : periodic_sf;
nr_timer_setup(&si->periodicBSR_Timer, target, 1); // 1 slot update rate
......
......@@ -77,6 +77,7 @@
#define MAX_NUM_BWP_UE 5
#define NUM_SLOT_FRAME 10
#define NR_MAX_SR_ID 8 // SchedulingRequestId ::= INTEGER (0..7)
/*!\brief value for indicating BSR Timer is not running */
#define NR_MAC_UE_BSR_TIMER_NOT_RUNNING (0xFFFF)
......@@ -202,33 +203,36 @@ typedef struct {
int32_t BSR_bytes;
} NR_LCG_SCHEDULING_INFO;
typedef struct {
bool active_SR_ID;
/// SR pending as defined in 38.321
bool pending;
/// SR_COUNTER as defined in 38.321
uint32_t counter;
/// sr ProhibitTimer
NR_timer_t prohibitTimer;
// Maximum number of SR transmissions
uint32_t maxTransmissions;
} nr_sr_info_t;
// LTE structure, might need to be adapted for NR
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
uint8_t BSR_reporting_active;
// LCID triggering BSR
NR_LogicalChannelIdentity_t regularBSR_trigger_lcid;
/// SR pending as defined in 38.321
uint8_t SR_pending;
/// SR_COUNTER as defined in 38.321
uint16_t SR_COUNTER;
// logicalChannelSR-DelayTimer
NR_timer_t sr_DelayTimer;
/// retxBSR-Timer
NR_timer_t retxBSR_Timer;
/// periodicBSR-Timer
NR_timer_t periodicBSR_Timer;
/// default value is 0: not configured
uint16_t sr_ProhibitTimer;
/// sr ProhibitTime running
uint8_t sr_ProhibitTimer_Running;
// Maximum number of SR transmissions
uint32_t sr_TransMax;
int sr_id;
///timer before triggering a periodic PHR
uint16_t periodicPHR_Timer;
///timer before triggering a prohibit PHR
......@@ -446,6 +450,7 @@ typedef struct ssb_list_info {
typedef struct nr_lcordered_info_s {
// logical channels ids ordered as per priority
NR_LogicalChannelIdentity_t lcid;
int sr_id;
long priority;
uint32_t pbr; // in B/s (UINT_MAX = infinite)
// Bucket size per lcid
......
......@@ -111,14 +111,11 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac,
void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info);
void nr_ue_dl_scheduler(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info);
/*! \fn int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP);
\brief Called by PHY to get sdu for PUSCH transmission. It performs the following operations: Checks BSR for DCCH, DCCH1 and
DTCH corresponding to previous values computed either in SR or BSR procedures. It gets rlc status indications on DCCH,DCCH1 and
DTCH and forms BSR elements and PHR in MAC header. CRNTI element is not supported yet. It computes transport block for up to 3
SDUs and generates header and forms the complete MAC SDU. \param[in] mac pointer to MAC instance \param[in] frameP
subframe number \param[in] slotP slot number
*/
int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP);
/*! \fn int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id);
\brief This function schedules a positive or negative SR for schedulingRequestID sr_id
depending on the presence of any active SR and the prohibit timer.
If the max number of retransmissions is reached, it triggers a new RA */
int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id);
nr_dci_format_t nr_ue_process_dci_indication_pdu(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci);
......
......@@ -79,6 +79,9 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment));
memset(mac->ssb_list, 0, sizeof(mac->ssb_list));
memset(mac->prach_assoc_pattern, 0, sizeof(mac->prach_assoc_pattern));
for (int i = 0; i < NR_MAX_SR_ID; i++)
memset(&mac->scheduling_info.sr_info[i], 0, sizeof(mac->scheduling_info.sr_info[i]));
}
void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac)
......@@ -166,6 +169,8 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
nr_timer_stop(&nr_mac->ra.contention_resolution_timer);
nr_timer_stop(&nr_mac->scheduling_info.sr_DelayTimer);
nr_timer_stop(&nr_mac->scheduling_info.retxBSR_Timer);
for (int i = 0; i < NR_MAX_SR_ID; i++)
nr_timer_stop(&nr_mac->scheduling_info.sr_info[i].prohibitTimer);
// consider all timeAlignmentTimers as expired and perform the corresponding actions in clause 5.2
// TODO
......@@ -185,11 +190,10 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
free_and_zero(nr_mac->ra.Msg3_buffer);
// cancel any triggered Scheduling Request procedure
nr_mac->scheduling_info.SR_COUNTER = 0;
nr_mac->scheduling_info.SR_pending = 0;
nr_mac->scheduling_info.sr_ProhibitTimer = 0;
nr_mac->scheduling_info.sr_ProhibitTimer_Running = 0;
nr_mac->scheduling_info.sr_id = -1; // invalid init value
for (int i = 0; i < NR_MAX_SR_ID; i++) {
nr_mac->scheduling_info.sr_info[i].pending = false;
nr_mac->scheduling_info.sr_info[i].counter = 0;
}
// cancel any triggered Buffer Status Reporting procedure
nr_mac->scheduling_info.BSR_reporting_active = NR_BSR_TRIGGER_NONE;
......
......@@ -2436,80 +2436,80 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *p
return false; // SR not configured
int sr_count = 0;
for (int SR_resource_id =0; SR_resource_id < pucch_Config->schedulingRequestResourceToAddModList->list.count;SR_resource_id++) {
NR_SchedulingRequestResourceConfig_t *SchedulingRequestResourceConfig = pucch_Config->schedulingRequestResourceToAddModList->list.array[SR_resource_id];
for (int id = 0; id < pucch_Config->schedulingRequestResourceToAddModList->list.count; id++) {
NR_SchedulingRequestResourceConfig_t *sr_Config = pucch_Config->schedulingRequestResourceToAddModList->list.array[id];
int SR_period; int SR_offset;
find_period_offset_SR(SchedulingRequestResourceConfig,&SR_period,&SR_offset);
find_period_offset_SR(sr_Config, &SR_period, &SR_offset);
const int n_slots_frame = nr_slots_per_frame[current_UL_BWP->scs];
int sfn_sf = frame * n_slots_frame + slot;
if ((sfn_sf - SR_offset) % SR_period == 0) {
LOG_D(MAC, "Scheduling Request active in frame %d slot %d \n", frame, slot);
if (!SchedulingRequestResourceConfig->resource) {
if (!sr_Config->resource) {
LOG_E(MAC, "No resource associated with SR. SR not scheduled\n");
break;
}
NR_PUCCH_Resource_t *sr_pucch =
find_pucch_resource_from_list(pucch_Config->resourceToAddModList, *SchedulingRequestResourceConfig->resource);
find_pucch_resource_from_list(pucch_Config->resourceToAddModList, *sr_Config->resource);
AssertFatal(sr_pucch != NULL, "Couldn't find PUCCH Resource ID for SR in PUCCH resource list\n");
pucch->pucch_resource = sr_pucch;
pucch->n_sr = 1;
/* sr_payload = 1 means that this is a positive SR, sr_payload = 0 means that it is a negative SR */
pucch->sr_payload = nr_ue_get_SR(mac, frame, slot, sr_Config->schedulingRequestID);
sr_count++;
AssertFatal(sr_count < 2, "Cannot handle more than 1 SR per slot yet\n");
}
}
AssertFatal(sr_count < 2, "Cannot handle more than 1 SR per slot yet\n");
return sr_count > 0 ? true : false;
}
int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slot)
int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id)
{
// no UL-SCH resources available for this tti && UE has a valid PUCCH resources for SR configuration for this tti
NR_UE_SCHEDULING_INFO *si = &mac->scheduling_info;
int max_sr_transmissions = (1 << (2 + si->sr_TransMax));
LOG_D(NR_MAC, "[UE %d] Frame %d slot %d send SR indication (SR_COUNTER/sr_TransMax %d/%d), SR_pending %d\n",
nr_sr_info_t *sr_info = &si->sr_info[sr_id];
if (!sr_info->active_SR_ID) {
LOG_E(NR_MAC, "SR triggered for an inactive SR with ID %ld\n", sr_id);
return 0;
}
LOG_D(NR_MAC, "[UE %d] Frame %d slot %d SR %s for ID %ld\n",
mac->ue_id,
frameP,
frame,
slot,
si->SR_COUNTER,
max_sr_transmissions,
si->SR_pending); // todo
sr_info->pending ? "pending" : "not pending",
sr_id); // todo
// TODO check if the PUCCH resource for the SR transmission occasion does not overlap with a UL-SCH resource
if (!sr_info->pending || is_nr_timer_active(sr_info->prohibitTimer))
return 0;
if ((si->SR_pending == 1) &&
(si->SR_COUNTER < max_sr_transmissions)) {
LOG_D(NR_MAC, "[UE %d] Frame %d slot %d PHY asks for SR (SR_COUNTER/sr_TransMax %d/%d), SR_pending %d, increment SR_COUNTER\n",
if (sr_info->counter < sr_info->maxTransmissions) {
sr_info->counter++;
// start the sr-prohibittimer
nr_timer_start(&sr_info->prohibitTimer);
LOG_D(NR_MAC, "[UE %d] Frame %d slot %d instruct the physical layer to signal the SR (counter/sr_TransMax %d/%d)\n",
mac->ue_id,
frameP,
frame,
slot,
si->SR_COUNTER,
max_sr_transmissions,
si->SR_pending); // todo
si->SR_COUNTER++;
// start the sr-prohibittimer : rel 9 and above
if (si->sr_ProhibitTimer > 0) { // timer configured
si->sr_ProhibitTimer--;
si->sr_ProhibitTimer_Running = 1;
} else {
si->sr_ProhibitTimer_Running = 0;
}
//mac->ul_active =1;
return (1); //instruct phy to signal SR
} else {
// notify RRC to relase PUCCH/SRS
// clear any configured dl/ul
// initiate RA
if (si->SR_pending) {
// release all pucch resource
//mac->physicalConfigDedicated = NULL; // todo
//mac->ul_active = 0; // todo
si->BSR_reporting_active = NR_BSR_TRIGGER_NONE;
LOG_I(NR_MAC, "[UE %d] Release all SRs \n", mac->ue_id);
}
si->SR_pending = 0;
si->SR_COUNTER = 0;
return (0);
sr_info->counter,
sr_info->maxTransmissions);
return 1;
}
// TODO
// notify RRC to release PUCCH for all Serving Cells;
// notify RRC to release SRS for all Serving Cells;
// clear any configured downlink assignments and uplink grants;
// clear any PUSCH resources for semi-persistent CSI reporting;
// initiate a Random Access procedure (see clause 5.1) on the SpCell and cancel all pending SRs.
LOG_E(NR_MAC, "[UE %d] SR not served. Triggering of new RA procedure not implemented yet.\n", mac->ue_id);
sr_info->pending = false;
sr_info->counter = 0;
nr_timer_stop(&sr_info->prohibitTimer);
return 0;
}
// section 5.2.5 of 38.214
......
......@@ -133,6 +133,8 @@ static void trigger_regular_bsr(NR_UE_MAC_INST_t *mac, NR_LogicalChannelIdentity
void update_mac_timers(NR_UE_MAC_INST_t *mac)
{
nr_timer_tick(&mac->ra.contention_resolution_timer);
for (int j = 0; j < NR_MAX_SR_ID; j++)
nr_timer_tick(&mac->scheduling_info.sr_info[j].prohibitTimer);
nr_timer_tick(&mac->scheduling_info.sr_DelayTimer);
bool retxBSR_expired = nr_timer_tick(&mac->scheduling_info.retxBSR_Timer);
if (retxBSR_expired) {
......@@ -1107,9 +1109,31 @@ void nr_ue_dl_scheduler(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info
LOG_E(NR_MAC, "Internal error, no scheduled_response function\n");
}
static void nr_trigger_sr(NR_UE_MAC_INST_t *mac)
static void nr_update_sr(NR_UE_MAC_INST_t *mac)
{
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;
}
}
if (!data_avail) {
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) {
LOG_D(NR_MAC, "No pending data available -> Canceling pending SRs\n");
sr->pending = false;
sr->counter = 0;
nr_timer_stop(&sr->prohibitTimer);
}
}
}
// if a Regular BSR has been triggered and logicalChannelSR-DelayTimer is not running
if (((sched_info->BSR_reporting_active & NR_BSR_TRIGGER_REGULAR) == 0)
|| is_nr_timer_active(sched_info->sr_DelayTimer))
......@@ -1128,7 +1152,18 @@ static void nr_trigger_sr(NR_UE_MAC_INST_t *mac)
// TODO not implemented
// trigger SR
sched_info->SR_pending = 1;
if (lc_info->sr_id < 0 || lc_info->sr_id >= NR_MAX_SR_ID)
LOG_E(NR_MAC, "No SR corresponding to this LCID\n"); // TODO not sure what to do here
else {
nr_sr_info_t *sr = &sched_info->sr_info[lc_info->sr_id];
if (!sr->pending) {
LOG_D(NR_MAC, "Triggering SR for ID %d\n", lc_info->sr_id);
sr->pending = true;
sr->counter = 0;
// TODO 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
}
}
}
static void nr_update_bsr(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP, uint8_t gNB_index)
......@@ -1287,7 +1322,7 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
}
if(mac->state == UE_CONNECTED)
nr_trigger_sr(mac);
nr_update_sr(mac);
// update Bj for all active lcids before LCP procedure
LOG_D(NR_MAC, "====================[Frame %d][Slot %d]Logical Channel Prioritization===========\n", frame_tx, slot_tx);
......@@ -1946,8 +1981,7 @@ void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP, voi
// SR
if (mac->state == UE_CONNECTED && trigger_periodic_scheduling_request(mac, &pucch[0], frameP, slotP)) {
num_res++;
/* sr_payload = 1 means that this is a positive SR, sr_payload = 0 means that it is a negative SR */
pucch[0].sr_payload = nr_ue_get_SR(mac, frameP, slotP);
// TODO check if the PUCCH resource for the SR transmission occasion overlap with a UL-SCH resource
}
// CSI
......@@ -2533,10 +2567,8 @@ static int nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac,
bsr_t
*/
static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac,
int CC_id,
frame_t frame,
slot_t slot,
uint8_t gNB_index,
uint8_t *ulsch_buffer,
uint16_t buflen,
NR_UE_MAC_CE_INFO *mac_ce_p)
......@@ -2675,18 +2707,15 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac,
}
}
LOG_D(NR_MAC, "[UE %d][SR] Gave SDU to PHY, clearing any scheduling request\n", mac->ue_id);
sched_info->SR_pending = 0;
sched_info->SR_COUNTER = 0;
/* Actions when a BSR is sent */
if (mac_ce_p->bsr_ce_len) {
LOG_D(NR_MAC,
"[UE %d] MAC BSR Sent !! bsr (ce%d,hdr%d) buff_len %d\n",
"[UE %d] MAC BSR Sent! ce %d, hdr %d buff_len %d triggering LCID %ld\n",
mac->ue_id,
mac_ce_p->bsr_ce_len,
mac_ce_p->bsr_header_len,
buflen);
buflen,
sched_info->regularBSR_trigger_lcid);
// Reset ReTx BSR Timer
nr_timer_start(&sched_info->retxBSR_Timer);
// Reset Periodic Timer except when BSR is truncated
......@@ -2695,8 +2724,20 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac,
LOG_D(NR_MAC, "[UE %d] MAC Periodic BSR Timer Reset\n", mac->ue_id);
}
if (sched_info->regularBSR_trigger_lcid > 0) {
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 (lc_info->sr_id >= 0 && lc_info->sr_id < NR_MAX_SR_ID) {
LOG_D(NR_MAC, "[UE %d][SR] Gave SDU to PHY, clearing scheduling request with ID %d\n", mac->ue_id, lc_info->sr_id);
nr_sr_info_t *sr = &sched_info->sr_info[lc_info->sr_id];
sr->pending = false;
sr->counter = 0;
nr_timer_stop(&sr->prohibitTimer);
}
}
// Reset BSR Trigger flags
sched_info->BSR_reporting_active = NR_BSR_TRIGGER_NONE;
sched_info->regularBSR_trigger_lcid = 0;
}
}
......@@ -3079,7 +3120,7 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
//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, CC_id, frame, slot, gNB_index, ulsch_buffer, buflen, mac_ce_p);
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) {
......
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