Skip to content

Commit 52a5322

Browse files
carlo-galcodebot
authored andcommitted
sched: add unittest for SRB1 segmentation
Signed-off-by: Carlo Galiotto <[email protected]>
1 parent d57c698 commit 52a5322

File tree

8 files changed

+277
-71
lines changed

8 files changed

+277
-71
lines changed

lib/scheduler/policy/scheduler_time_rr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ static alloc_outcome alloc_dl_ue(const ue& u,
230230

231231
if (ue_cc.is_in_fallback_mode()) {
232232
// Skip allocation for UEs in fallback mode, as it is handled by the SRB0 scheduler.
233-
continue;
233+
return alloc_outcome::skip_ue;
234234
}
235235

236236
// UE is already allocated in the PDCCH for this slot (e.g. we should skip a newTx if a reTx has already been

lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,14 @@ optional<unsigned> pucch_allocator_impl::alloc_common_pucch_harq_ack_ue(cell_res
111111
return nullopt;
112112
}
113113

114+
if (has_common_pucch_f1_grant(tcrnti, pucch_slot_alloc.slot)) {
115+
logger.debug(
116+
"tc-rnti={}: PUCCH common not allocated for slot={}. Cause: existing grant for this UE at the same slot",
117+
tcrnti,
118+
pucch_slot_alloc.slot);
119+
return nullopt;
120+
}
121+
114122
// Get the PUCCH resources, either from default tables.
115123
optional<pucch_res_alloc_cfg> pucch_res = alloc_pucch_common_res_harq(pucch_slot_alloc, dci_info.ctx);
116124

lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp

Lines changed: 81 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ ue_srb0_scheduler::ue_srb0_scheduler(const scheduler_ue_expert_config& expert_cf
3434
cs_cfg(cell_cfg.get_common_coreset(ss_cfg.get_coreset_id())),
3535
logger(srslog::fetch_basic_logger("SCHED"))
3636
{
37+
// NOTE: We use a std::vector instead of a std::array because we can later on initialize the vector with the minimum
38+
// value of k1, passed through the expert config.
39+
dci_1_0_k1_values = {4, 5, 6, 7, 8};
3740
}
3841

3942
void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc)
@@ -58,12 +61,12 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc)
5861
auto* h_dl = next_ue_harq_retx->get_harq_process();
5962

6063
if (h_dl->has_pending_retx()) {
61-
optional<slot_point> most_recent_tx = get_most_recent_slot_tx(u.ue_index);
64+
optional<std::pair<slot_point, slot_point>> most_recent_tx_ack = get_most_recent_slot_tx(u.ue_index);
6265
if (next_ue_harq_retx->is_srb0) {
63-
schedule_srb(res_alloc, u, true, h_dl, most_recent_tx);
66+
schedule_srb(res_alloc, u, next_ue_harq_retx->is_srb0, h_dl, most_recent_tx_ack);
6467
} else {
6568
// TODO: Change this into SRB1_retx.
66-
schedule_srb(res_alloc, u, true, h_dl, most_recent_tx);
69+
schedule_srb(res_alloc, u, next_ue_harq_retx->is_srb0, h_dl, most_recent_tx_ack);
6770
}
6871
}
6972
++next_ue_harq_retx;
@@ -83,9 +86,9 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc)
8386
continue;
8487
}
8588

86-
auto& u = ues[next_ue->ue_index];
87-
optional<slot_point> most_recent_tx = get_most_recent_slot_tx(u.ue_index);
88-
if (u.has_pending_dl_newtx_bytes(LCID_SRB0) and schedule_srb(res_alloc, u, true, nullptr, most_recent_tx)) {
89+
auto& u = ues[next_ue->ue_index];
90+
optional<std::pair<slot_point, slot_point>> most_recent_tx_ack = get_most_recent_slot_tx(u.ue_index);
91+
if (u.has_pending_dl_newtx_bytes(LCID_SRB0) and schedule_srb(res_alloc, u, true, nullptr, most_recent_tx_ack)) {
8992
next_ue = pending_ues.erase(next_ue);
9093
} else {
9194
++next_ue;
@@ -106,10 +109,18 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc)
106109
continue;
107110
}
108111

109-
auto& u = ues[next_ue->ue_index];
110-
optional<slot_point> most_recent_tx = get_most_recent_slot_tx(u.ue_index);
111-
if (u.has_pending_dl_newtx_bytes(LCID_SRB1) and schedule_srb(res_alloc, u, false, nullptr, most_recent_tx)) {
112-
next_ue = pending_ues.erase(next_ue);
112+
auto& u = ues[next_ue->ue_index];
113+
optional<std::pair<slot_point, slot_point>> most_recent_tx_ack = get_most_recent_slot_tx(u.ue_index);
114+
if (u.has_pending_dl_newtx_bytes(LCID_SRB1) and schedule_srb(res_alloc, u, false, nullptr, most_recent_tx_ack)) {
115+
if (not u.has_pending_dl_newtx_bytes(LCID_SRB1)) {
116+
logger.debug("rnti={}: Removing UE from list, as SRB1 buffer is empty.", u.crnti);
117+
next_ue = pending_ues.erase(next_ue);
118+
}
119+
// Don't increase the iterator here, as we give priority to the same UE if there left are bytes in the SRB1
120+
// buffer.
121+
// NOTE: The policy we adopt in this scheduler is to schedule first the all possible grants to a given UE,
122+
// to speed up the re-establishment and re-configuration for that UE. Only after the SRB1 buffer of the UE is
123+
// emptied, we move on to the next UE.
113124
} else {
114125
++next_ue;
115126
}
@@ -137,11 +148,11 @@ static slot_point get_next_srb_slot(const cell_configuration& cell_cfg, slot_poi
137148
return next_candidate_slot;
138149
}
139150

140-
bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc,
141-
ue& u,
142-
bool is_srb0,
143-
dl_harq_process* h_dl_retx,
144-
optional<slot_point> starting_sl)
151+
bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc,
152+
ue& u,
153+
bool is_srb0,
154+
dl_harq_process* h_dl_retx,
155+
optional<std::pair<slot_point, slot_point>> most_recent_tx_ack_slots)
145156
{
146157
const auto& bwp_cfg_common = cell_cfg.dl_cfg_common.init_dl_bwp;
147158
// Search valid PDSCH time domain resource.
@@ -160,14 +171,17 @@ bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc,
160171
return false;
161172
}
162173

163-
if (starting_sl.has_value() and sched_ref_slot + max_dl_slots_ahead_sched < starting_sl.value()) {
174+
if (most_recent_tx_ack_slots.has_value() and
175+
sched_ref_slot + max_dl_slots_ahead_sched < most_recent_tx_ack_slots.value().first) {
164176
return false;
165177
}
166-
starting_sl = sched_ref_slot;
167178

168179
// We keep track of the number of scheduling attempts for the given UE.
169180
unsigned sched_attempts_cnt = 0;
170-
slot_point next_slot = starting_sl.value();
181+
slot_point next_slot =
182+
most_recent_tx_ack_slots.has_value() and most_recent_tx_ack_slots.value().first > sched_ref_slot
183+
? most_recent_tx_ack_slots.value().first
184+
: sched_ref_slot;
171185

172186
while (next_slot <= sched_ref_slot + max_dl_slots_ahead_sched) {
173187
unsigned offset_to_sched_ref_slot = static_cast<unsigned>(next_slot - sched_ref_slot);
@@ -215,15 +229,26 @@ bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc,
215229
return false;
216230
}
217231

232+
slot_point most_recent_ack_slot = pdsch_alloc.slot;
233+
if (most_recent_tx_ack_slots.has_value()) {
234+
if (pdsch_alloc.slot + dci_1_0_k1_values.back() <= most_recent_tx_ack_slots.value().second) {
235+
continue;
236+
}
237+
most_recent_ack_slot = most_recent_tx_ack_slots.value().second;
238+
}
239+
218240
dl_harq_process* candidate_h_dl =
219-
is_srb0 ? schedule_srb0(u, res_alloc, time_res_idx, offset_to_sched_ref_slot, h_dl_retx)
220-
: schedule_srb1(u, res_alloc, time_res_idx, offset_to_sched_ref_slot, h_dl_retx);
241+
is_srb0
242+
? schedule_srb0(u, res_alloc, time_res_idx, offset_to_sched_ref_slot, most_recent_ack_slot, h_dl_retx)
243+
: schedule_srb1(u, res_alloc, time_res_idx, offset_to_sched_ref_slot, most_recent_ack_slot, h_dl_retx);
221244

222245
const bool alloc_successful = candidate_h_dl != nullptr;
223246
if (alloc_successful) {
224247
if (not is_retx) {
225248
store_harq_tx(u.ue_index, candidate_h_dl, is_srb0);
226249
}
250+
logger.debug(
251+
"rnti={}: PDSCH space for SRB{} scheduled for slot:{}", u.crnti, is_srb0 ? "0" : "1", pdsch_alloc.slot);
227252
return true;
228253
}
229254

@@ -235,7 +260,7 @@ bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc,
235260

236261
// No resource found in UE's carriers and Search spaces.
237262
slot_point pdcch_slot = res_alloc[0].slot;
238-
logger.debug("rnti={}: Not enough PDSCH space for {} message found in any of the slots:[{},{}).",
263+
logger.debug("rnti={}: Not enough PDSCH space for {} message found in any of the slots:[{},{})",
239264
u.crnti,
240265
is_srb0 ? "SRB0" : "SRB1",
241266
pdcch_slot,
@@ -247,6 +272,7 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u,
247272
cell_resource_allocator& res_alloc,
248273
unsigned pdsch_time_res,
249274
unsigned slot_offset,
275+
slot_point most_recent_ack_slot,
250276
dl_harq_process* h_dl_retx)
251277
{
252278
ue_cell& ue_pcell = u.get_pcell();
@@ -306,7 +332,7 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u,
306332

307333
if (prbs_tbs.tbs_bytes < pending_bytes) {
308334
logger.debug(
309-
"rnti={}: SRB0 PDU size ({}) exceeds TBS calculated ({}).", pending_bytes, prbs_tbs.tbs_bytes, u.crnti);
335+
"rnti={}: SRB0 PDU size ({}) exceeds TBS calculated ({})", pending_bytes, prbs_tbs.tbs_bytes, u.crnti);
310336
return nullptr;
311337
}
312338

@@ -334,16 +360,20 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u,
334360
pdcch_dl_information* pdcch =
335361
pdcch_sch.alloc_dl_pdcch_common(pdcch_alloc, u.crnti, ss_cfg.get_id(), aggregation_level::n4);
336362
if (pdcch == nullptr) {
337-
logger.debug("rnti={}: Postponed SRB0 PDU scheduling. Cause: No space in PDCCH.", u.crnti);
363+
logger.debug(
364+
"rnti={}: Postponed SRB0 PDU scheduling for slot. Cause: No space in PDCCH.", u.crnti, pdsch_alloc.slot);
338365
return nullptr;
339366
}
340367

341368
// Allocate PUCCH resources.
342-
unsigned k1 = 4;
369+
unsigned k1 = dci_1_0_k1_values.front();
343370
// Minimum k1 value supported is 4.
344-
static const std::array<uint8_t, 5> dci_1_0_k1_values = {4, 5, 6, 7, 8};
345-
optional<unsigned> pucch_res_indicator;
371+
optional<unsigned> pucch_res_indicator;
346372
for (const auto k1_candidate : dci_1_0_k1_values) {
373+
// Skip k1 values that would result in a PUCCH transmission in a slot that is older than the most recent ACK slot.
374+
if (pdsch_alloc.slot + k1_candidate <= most_recent_ack_slot) {
375+
continue;
376+
}
347377
pucch_res_indicator = pucch_alloc.alloc_common_pucch_harq_ack_ue(
348378
res_alloc, u.crnti, slot_offset + pdsch_td_cfg.k0, k1_candidate, *pdcch);
349379
if (pucch_res_indicator.has_value()) {
@@ -352,7 +382,8 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u,
352382
}
353383
}
354384
if (not pucch_res_indicator.has_value()) {
355-
logger.debug("Failed to allocate PDSCH for SRB0. Cause: No space in PUCCH.");
385+
logger.debug(
386+
"rnti={}: Failed to allocate PDSCH for SRB0 for slot={}. Cause: No space in PUCCH", u.crnti, pdsch_alloc.slot);
356387
pdcch_sch.cancel_last_pdcch(pdcch_alloc);
357388
return nullptr;
358389
}
@@ -381,6 +412,7 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb1(ue& u,
381412
cell_resource_allocator& res_alloc,
382413
unsigned pdsch_time_res,
383414
unsigned slot_offset,
415+
slot_point most_recent_ack_slot,
384416
dl_harq_process* h_dl_retx)
385417
{
386418
ue_cell& ue_pcell = u.get_pcell();
@@ -490,11 +522,14 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb1(ue& u,
490522
}
491523

492524
// Allocate PUCCH resources.
493-
unsigned k1 = 4;
525+
unsigned k1 = dci_1_0_k1_values.front();
494526
// Minimum k1 value supported is 4.
495-
static const std::array<uint8_t, 5> dci_1_0_k1_values = {4, 5, 6, 7, 8};
496-
optional<unsigned> pucch_res_indicator;
527+
optional<unsigned> pucch_res_indicator;
497528
for (const auto k1_candidate : dci_1_0_k1_values) {
529+
// Skip the k1 values that would result in a PUCCH allocation that would overlap with the most recent ACK slot.
530+
if (pdsch_alloc.slot + k1_candidate <= most_recent_ack_slot) {
531+
continue;
532+
}
498533
pucch_res_indicator = pucch_alloc.alloc_common_pucch_harq_ack_ue(
499534
res_alloc, u.crnti, slot_offset + pdsch_td_cfg.k0, k1_candidate, *pdcch);
500535
if (pucch_res_indicator.has_value()) {
@@ -503,7 +538,8 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb1(ue& u,
503538
}
504539
}
505540
if (not pucch_res_indicator.has_value()) {
506-
logger.debug("Failed to allocate PDSCH for SRB0. Cause: No space in PUCCH.");
541+
logger.debug(
542+
"rnti={}: Failed to allocate PDSCH for SRB0 for slot={}. Cause: No space in PUCCH", u.crnti, pdsch_alloc.slot);
507543
pdcch_sch.cancel_last_pdcch(pdcch_alloc);
508544
return nullptr;
509545
}
@@ -713,20 +749,26 @@ const pdsch_time_domain_resource_allocation& ue_srb0_scheduler::get_pdsch_td_cfg
713749
return cell_cfg.dl_cfg_common.init_dl_bwp.pdsch_common.pdsch_td_alloc_list[pdsch_time_res_idx];
714750
}
715751

716-
optional<slot_point> ue_srb0_scheduler::get_most_recent_slot_tx(du_ue_index_t ue_idx) const
752+
optional<std::pair<slot_point, slot_point>> ue_srb0_scheduler::get_most_recent_slot_tx(du_ue_index_t ue_idx) const
717753
{
718-
optional<slot_point> most_recent_tx;
754+
optional<std::pair<slot_point, slot_point>> most_recent_tx_ack_slot;
719755
for (const auto& ue_proc : ongoing_ues_ack_retxs) {
720756
if (ue_proc.ue_index == ue_idx) {
721-
slot_point h_dl_slot_tx = ue_proc.get_harq_process()->slot_tx();
722-
if (most_recent_tx.has_value() and h_dl_slot_tx > most_recent_tx.value()) {
723-
most_recent_tx = ue_proc.get_harq_process()->slot_tx();
724-
} else {
725-
most_recent_tx.emplace(ue_proc.get_harq_process()->slot_tx());
757+
slot_point h_dl_slot_tx = ue_proc.get_harq_process()->slot_tx();
758+
slot_point h_dl_slot_ack = ue_proc.get_harq_process()->slot_ack();
759+
if (not most_recent_tx_ack_slot.has_value()) {
760+
most_recent_tx_ack_slot.emplace(h_dl_slot_tx, h_dl_slot_ack);
761+
continue;
762+
}
763+
if (h_dl_slot_tx > most_recent_tx_ack_slot.value().first) {
764+
most_recent_tx_ack_slot.value().first = h_dl_slot_tx;
765+
}
766+
if (h_dl_slot_ack > most_recent_tx_ack_slot.value().second) {
767+
most_recent_tx_ack_slot.value().second = h_dl_slot_ack;
726768
}
727769
}
728770
}
729-
return most_recent_tx;
771+
return most_recent_tx_ack_slot;
730772
}
731773

732774
void ue_srb0_scheduler::store_harq_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0)

lib/scheduler/ue_scheduling/ue_srb0_scheduler.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,26 @@ class ue_srb0_scheduler
4343
void update_ongoing_ue_retxs();
4444

4545
/// \brief Tries to schedule SRB0 message for a UE. Returns true if successful, false otherwise.
46-
bool schedule_srb(cell_resource_allocator& res_alloc,
47-
ue& u,
48-
bool is_srb0,
49-
dl_harq_process* h_dl_retx,
50-
optional<slot_point> starting_sl);
46+
bool schedule_srb(cell_resource_allocator& res_alloc,
47+
ue& u,
48+
bool is_srb0,
49+
dl_harq_process* h_dl_retx,
50+
optional<std::pair<slot_point, slot_point>> most_recent_tx_ack_slots);
5151

5252
/// \brief Tries to schedule SRB0 message for a UE and a specific PDSCH TimeDomain Resource and Search Space.
5353
dl_harq_process* schedule_srb0(ue& u,
5454
cell_resource_allocator& res_alloc,
5555
unsigned pdsch_time_res,
5656
unsigned slot_offset,
57+
slot_point most_recent_ack_slot,
5758
dl_harq_process* h_dl_retx);
5859

5960
/// \brief Tries to schedule SRB0 message for a UE and a specific PDSCH TimeDomain Resource and Search Space.
6061
dl_harq_process* schedule_srb1(ue& u,
6162
cell_resource_allocator& res_alloc,
6263
unsigned pdsch_time_res,
6364
unsigned slot_offset,
65+
slot_point most_recent_ack_slot,
6466
dl_harq_process* h_dl_retx = nullptr);
6567

6668
void fill_srb0_grant(ue& u,
@@ -132,7 +134,10 @@ class ue_srb0_scheduler
132134

133135
void store_harq_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0);
134136

135-
optional<slot_point> get_most_recent_slot_tx(du_ue_index_t ue_idx) const;
137+
// If there is any pending SRB0 or SRB1 transmissions for the UE, the function returns the most recent slot with PDSCH
138+
// for SRB0/SRB1 (first element of the pair) and the most recent slot with the corresponding PUCCH (first element of
139+
// the pair).
140+
optional<std::pair<slot_point, slot_point>> get_most_recent_slot_tx(du_ue_index_t ue_idx) const;
136141

137142
const scheduler_ue_expert_config& expert_cfg;
138143
const cell_configuration& cell_cfg;
@@ -154,6 +159,8 @@ class ue_srb0_scheduler
154159
/// Cache the UEs that are waiting for SRB HARQ processes to be ACKed or retransmitted.
155160
std::list<ack_and_retx_tracker> ongoing_ues_ack_retxs;
156161

162+
std::vector<uint8_t> dci_1_0_k1_values;
163+
157164
srslog::basic_logger& logger;
158165
};
159166

tests/unittests/scheduler/multiple_ue_sched_test.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -467,11 +467,11 @@ class scheduler_impl_tester
467467
uci_indication::uci_pdu::uci_pucch_f0_or_f1_pdu pucch_pdu{};
468468
if (pucch.format == pucch_format::FORMAT_0) {
469469
pucch_pdu.sr_detected = sr_nof_bits_to_uint(pucch.format_0.sr_bits) > 0;
470-
// Auto ACK harqs.
470+
// Auto ACK latest_harq_states.
471471
pucch_pdu.harqs.resize(pucch.format_0.harq_ack_nof_bits, mac_harq_ack_report_status::ack);
472472
} else {
473473
pucch_pdu.sr_detected = sr_nof_bits_to_uint(pucch.format_1.sr_bits) > 0;
474-
// Auto ACK harqs.
474+
// Auto ACK latest_harq_states.
475475
pucch_pdu.harqs.resize(pucch.format_1.harq_ack_nof_bits, mac_harq_ack_report_status::ack);
476476
}
477477
pucch_pdu.ul_sinr = 55;
@@ -482,7 +482,7 @@ class scheduler_impl_tester
482482
uci_indication::uci_pdu::uci_pucch_f2_or_f3_or_f4_pdu pucch_pdu{};
483483
pucch_pdu.sr_info.resize(sr_nof_bits_to_uint(pucch.format_2.sr_bits));
484484
pucch_pdu.sr_info.fill(0, sr_nof_bits_to_uint(pucch.format_2.sr_bits), true);
485-
// Auto ACK harqs.
485+
// Auto ACK latest_harq_states.
486486
pucch_pdu.harqs.resize(pucch.format_2.harq_ack_nof_bits, mac_harq_ack_report_status::ack);
487487
if (pucch.csi_rep_cfg.has_value()) {
488488
pucch_pdu.csi.emplace();
@@ -507,7 +507,7 @@ class scheduler_impl_tester
507507
pdu.ue_index = bench->rnti_to_du_ue_index(pdu.crnti);
508508

509509
uci_indication::uci_pdu::uci_pusch_pdu pusch_pdu{};
510-
// Auto ACK harqs.
510+
// Auto ACK latest_harq_states.
511511
if (pusch.uci->harq.has_value()) {
512512
pusch_pdu.harqs.resize(pusch.uci->harq->harq_ack_nof_bits, mac_harq_ack_report_status::ack);
513513
}

0 commit comments

Comments
 (0)