Merge remote-tracking branch 'origin/fixes-ul-sched' into integration_2025_w37 (!3635)

Fixes and updates for UL scheduling, notably DSUUU

Fix a number of problems that stem from !3521, notably regarding Msg3
scheduling, retransmissions in "UL-heavy" TDD scenarios, and BSR
handling. Modify a CI test to run a UL-heavy TDD scenario, and add
documentation for UL-heavy TDD scenarios.
This commit is contained in:
Robert Schmidt
2025-09-11 19:48:48 +02:00
11 changed files with 67 additions and 35 deletions
@@ -138,6 +138,10 @@ static uint8_t set_tdd_bmap_period(const NR_TDD_UL_DL_Pattern_t *pattern, tdd_pe
n_ul_slot,
n_dl_symbols,
n_ul_symbols);
AssertFatal(n_dl_symbols + n_ul_symbols < 14,
"number of mixed slot symbols must be smaller than 14: DL %d, UL %d\n",
n_dl_symbols,
n_ul_symbols);
return total_slot;
}
@@ -174,6 +178,11 @@ static void config_tdd_patterns(const NR_TDD_UL_DL_ConfigCommon_t *tdd, frame_st
num_of_patterns,
nb_slots_p1,
nb_slots_p2);
AssertFatal(nb_slots_p1 + nb_slots_p2 == fs->numb_slots_period,
"total number of slots must equal to %d: p1 %d + p2 %d\n",
fs->numb_slots_period,
nb_slots_p1,
nb_slots_p2);
}
/**
@@ -595,6 +595,7 @@ static int nr_process_mac_pdu(instance_t module_idP,
/* Extract short BSR value */
ce_ptr = &pduP[mac_subheader_len];
sched_ctrl->estimated_ul_buffer = estimate_ul_buffer_short_bsr((NR_BSR_SHORT *)ce_ptr);
sched_ctrl->sched_ul_bytes = 0;
LOG_D(NR_MAC, "SHORT BSR at %4d.%2d, est buf %d\n", frameP, slot, sched_ctrl->estimated_ul_buffer);
break;
@@ -603,6 +604,7 @@ static int nr_process_mac_pdu(instance_t module_idP,
/* Extract long BSR value */
ce_ptr = &pduP[mac_subheader_len];
sched_ctrl->estimated_ul_buffer = estimate_ul_buffer_long_bsr((NR_BSR_LONG *)ce_ptr);
sched_ctrl->sched_ul_bytes = 0;
LOG_D(NR_MAC, "LONG BSR at %4d.%2d, estim buf %d\n", frameP, slot, sched_ctrl->estimated_ul_buffer);
break;
@@ -1805,7 +1807,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac,
new_sched.bwp_info = bwp_info;
DevAssert(new_sched.ul_harq_pid == harq_pid);
bool reuse_old_tda = (retInfo->tda_info.startSymbolIndex == tda_info->startSymbolIndex) && (retInfo->tda_info.nrOfSymbols <= tda_info->nrOfSymbols);
bool reuse_old_tda = retInfo->time_domain_allocation == tda;
if (reuse_old_tda && nrOfLayers == retInfo->nrOfLayers) {
/* Check the resource is enough for retransmission */
const uint16_t slbitmap = SL_to_bitmap(retInfo->tda_info.startSymbolIndex, retInfo->tda_info.nrOfSymbols);
@@ -1887,6 +1889,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac,
fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam_idx);
// signal new allocation
DevAssert(new_sched.time_domain_allocation == tda);
post_process_ulsch(nrmac, pp_pusch, UE, &new_sched);
LOG_D(NR_MAC,
"%4d.%2d Allocate UL retransmission RNTI %04x sched %4d.%2d (%d RBs)\n",
@@ -2424,16 +2427,11 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE
/* Statistics */
AssertFatal(cur_harq->round < nr_mac->ul_bler.harq_round_max, "Indexing ulsch_rounds[%d] is out of bounds\n", cur_harq->round);
UE->mac_stats.ul.rounds[cur_harq->round]++;
/* Save information on MCS, TBS etc for the current initial transmission
* so we have access to it when retransmitting */
cur_harq->sched_pusch = *sched_pusch;
if (cur_harq->round == 0) {
UE->mac_stats.ulsch_total_bytes_scheduled += sched_pusch->tb_size;
/* Save information on MCS, TBS etc for the current initial transmission
* so we have access to it when retransmitting */
cur_harq->sched_pusch = *sched_pusch;
/* save which time allocation and nrOfLayers have been used, to be used on
* retransmissions */
cur_harq->sched_pusch.time_domain_allocation = sched_pusch->time_domain_allocation;
cur_harq->sched_pusch.nrOfLayers = sched_pusch->nrOfLayers;
cur_harq->sched_pusch.tpmi = sched_pusch->tpmi;
sched_ctrl->sched_ul_bytes += sched_pusch->tb_size;
UE->mac_stats.ul.total_rbs += sched_pusch->rbSize;
+24 -6
View File
@@ -1123,20 +1123,22 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay, i
// make TDA for the mixed slot
long mixed_sliv = get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1);
if (ul_symb > 1 && (k2 <= N_dl1 || (p2 && N_ul2 == 0))) {
int mixed_min_ul_symb = 3; // need at least two symbols PUSCH + PUCCH
bool has_ul_mixed = ul_symb >= mixed_min_ul_symb;
if (has_ul_mixed && (k2 <= N_dl1 || (p2 && N_ul2 == 0))) {
// UL TDA index 2 for mixed slot (TDD) (no pattern 2 and enough DL slots, or pattern2 only DL)
tda = set_TimeDomainResourceAllocation(k2, mixed_sliv); // to be reached from suitable DL slot
asn1cSeqAdd(&tda_list->list, tda);
} else if (ul_symb > 1 && !p2 && k2 > N_dl1) { // k2 > N_Dl1
} else if (has_ul_mixed && !p2 && k2 > N_dl1) { // k2 > N_Dl1
// UL TDA for mixed slot without pattern 2 and less DL slots than k2
tda = set_TimeDomainResourceAllocation(nb_slots_per_period, mixed_sliv); // to be reached from last DL (mixed) slot, if any
asn1cSeqAdd(&tda_list->list, tda);
} else if (ul_symb > 1 && N_ul2 > 0 && k2 > N_dl1) {
} else if (has_ul_mixed && N_ul2 > 0 && k2 > N_dl1) {
// we have pattern 2 with UL, and less p1 DL slots than k2
tda = set_TimeDomainResourceAllocation(N_dl1 + N_ul2 + 1, mixed_sliv);
asn1cSeqAdd(&tda_list->list, tda);
} else {
AssertFatal(ul_symb == 0, "unhandled case of mixed slot: N_dl1 %d N_ul1 %d N_dl2 %d N_ul2 %d\n", N_dl1, N_ul1, N_dl2, N_ul2);
LOG_I(NR_RRC, "mixed slot has %d UL symbols, cannot create mixed slot TDA\n", ul_symb);
}
// make TDA for UL slots that are not reachable within k2/min_rxtxtime
@@ -1149,11 +1151,27 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay, i
tda = set_TimeDomainResourceAllocation(i, get_SLIV(0, 13));
asn1cSeqAdd(&tda_list->list, tda);
if (do_SRS) {
tda = set_TimeDomainResourceAllocation(k2, get_SLIV(0, 12));
tda = set_TimeDomainResourceAllocation(i, get_SLIV(0, 12));
asn1cSeqAdd(&tda_list->list, tda);
}
}
}
// for Msg3, an additional get_delta_for_k2(mu) is added to k2.
// check that any UL slot is reachable under this condition
// the below is designed to only hit specific (known) cases
// examples: DDDSU (no TDA in S),
int N_dl = max(N_dl1, N_dl2);
int delta = get_delta_for_k2(mu);
int k2_msg3 = k2 + delta;
if (nb_slots_per_period % k2_msg3 == 0 /* see example above */
&& k2_msg3 > N_dl /* otherwise, can always have a D that reaches U */
&& k2_msg3 > N_ul /* otherwise, can always have a D that reaches U */
&& !has_ul_mixed /* if mixed slot, even for DDDSU would reach */) {
/* reach next UL from mixed slot in previous period */
tda = set_TimeDomainResourceAllocation(k2_msg3, get_SLIV(0, 13));
asn1cSeqAdd(&tda_list->list, tda);
}
}
AssertFatal(tda_list->list.count <= 16, "cannot reach all UL slots with current TDD configuration\n");
@@ -2988,7 +3006,7 @@ static NR_MAC_CellGroupConfig_t *configure_mac_cellgroup(const nr_mac_timers_t *
NR_MAC_CellGroupConfig_t * mac_CellGroupConfig = calloc(1, sizeof(*mac_CellGroupConfig));
AssertFatal(mac_CellGroupConfig != NULL, "Couldn't allocate mac-CellGroupConfig. Out of memory!\n");
mac_CellGroupConfig->bsr_Config = calloc(1, sizeof(*mac_CellGroupConfig->bsr_Config));
mac_CellGroupConfig->bsr_Config->periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_sf10;
mac_CellGroupConfig->bsr_Config->periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_sf5;
mac_CellGroupConfig->bsr_Config->retxBSR_Timer = NR_BSR_Config__retxBSR_Timer_sf80;
mac_CellGroupConfig->tag_Config = calloc(1, sizeof(*mac_CellGroupConfig->tag_Config));
mac_CellGroupConfig->tag_Config->tag_ToReleaseList = NULL;