|
15 | 15 |
|
16 | 16 | using namespace srsran; |
17 | 17 |
|
| 18 | +class ue_event_manager::ue_dl_buffer_occupancy_manager |
| 19 | +{ |
| 20 | +public: |
| 21 | + ue_dl_buffer_occupancy_manager(ue_event_manager& parent_) : parent(parent_) |
| 22 | + { |
| 23 | + std::fill(ue_rlc_bo_list.begin(), ue_rlc_bo_list.end(), -1); |
| 24 | + } |
| 25 | + |
| 26 | + void enqueue_rlc_buffer_occupancy_update(const dl_buffer_state_indication_message& rlc_dl_bo) |
| 27 | + { |
| 28 | + unsigned idx = rlc_dl_bo.ue_index * MAX_NOF_RB_LCIDS + rlc_dl_bo.lcid; |
| 29 | + bool first_rlc_bo = ue_rlc_bo_list[idx].exchange(rlc_dl_bo.bs, std::memory_order_acquire) < 0; |
| 30 | + |
| 31 | + if (not first_rlc_bo) { |
| 32 | + return; |
| 33 | + } |
| 34 | + |
| 35 | + pending_evs.push(rlc_dl_bo); |
| 36 | + } |
| 37 | + |
| 38 | + void slot_indication() |
| 39 | + { |
| 40 | + // Retrieve pending UEs. |
| 41 | + pending_evs.slot_indication(); |
| 42 | + span<dl_buffer_state_indication_message> ues_to_process = pending_evs.get_events(); |
| 43 | + |
| 44 | + // Process RLC buffer updates of pending UEs. |
| 45 | + for (dl_buffer_state_indication_message& dl_bo : ues_to_process) { |
| 46 | + if (not parent.ue_db.contains(dl_bo.ue_index)) { |
| 47 | + parent.log_invalid_ue_index(dl_bo.ue_index); |
| 48 | + continue; |
| 49 | + } |
| 50 | + ue& u = parent.ue_db[dl_bo.ue_index]; |
| 51 | + |
| 52 | + // Update DL buffer state with latest RLC buffer occupancy update for this UE. |
| 53 | + unsigned idx = dl_bo.ue_index * MAX_NOF_RB_LCIDS + dl_bo.lcid; |
| 54 | + dl_bo.bs = ue_rlc_bo_list[idx].exchange(-1, std::memory_order_acq_rel); |
| 55 | + |
| 56 | + // Forward DL buffer state to UE. |
| 57 | + u.handle_dl_buffer_state_indication(dl_bo); |
| 58 | + if (dl_bo.lcid == LCID_SRB0) { |
| 59 | + // Signal SRB0 scheduler with the new SRB0 buffer state. |
| 60 | + parent.du_cells[u.get_pcell().cell_index].srb0_sched->handle_dl_buffer_state_indication(dl_bo.ue_index); |
| 61 | + } |
| 62 | + |
| 63 | + // Log event. |
| 64 | + parent.ev_logger.enqueue(dl_bo); |
| 65 | + |
| 66 | + // Report event. |
| 67 | + parent.metrics_handler.handle_dl_buffer_state_indication(dl_bo); |
| 68 | + } |
| 69 | + } |
| 70 | + |
| 71 | +private: |
| 72 | + ue_event_manager& parent; |
| 73 | + |
| 74 | + std::array<std::atomic<int>, MAX_NOF_DU_UES * MAX_NOF_RB_LCIDS> ue_rlc_bo_list; |
| 75 | + |
| 76 | + slot_event_list<dl_buffer_state_indication_message> pending_evs; |
| 77 | +}; |
| 78 | + |
18 | 79 | ue_event_manager::ue_event_manager(ue_repository& ue_db_, |
19 | 80 | scheduler_metrics_handler& metrics_handler_, |
20 | 81 | scheduler_event_logger& ev_logger_) : |
21 | | - ue_db(ue_db_), metrics_handler(metrics_handler_), ev_logger(ev_logger_), logger(srslog::fetch_basic_logger("SCHED")) |
| 82 | + ue_db(ue_db_), |
| 83 | + metrics_handler(metrics_handler_), |
| 84 | + ev_logger(ev_logger_), |
| 85 | + logger(srslog::fetch_basic_logger("SCHED")), |
| 86 | + dl_bo_mng(std::make_unique<ue_dl_buffer_occupancy_manager>(*this)) |
22 | 87 | { |
23 | 88 | } |
24 | 89 |
|
| 90 | +ue_event_manager::~ue_event_manager() {} |
| 91 | + |
25 | 92 | void ue_event_manager::handle_ue_creation(ue_config_update_event ev) |
26 | 93 | { |
27 | 94 | // Create UE object outside the scheduler slot indication handler to minimize latency. |
@@ -323,30 +390,13 @@ void ue_event_manager::handle_dl_mac_ce_indication(const dl_mac_ce_indication& c |
323 | 390 |
|
324 | 391 | void ue_event_manager::handle_dl_buffer_state_indication(const dl_buffer_state_indication_message& bs) |
325 | 392 | { |
326 | | - common_events.emplace(bs.ue_index, [this, bs]() { |
327 | | - if (not ue_db.contains(bs.ue_index)) { |
328 | | - log_invalid_ue_index(bs.ue_index, "DL Buffer State"); |
329 | | - return; |
330 | | - } |
331 | | - ue& u = ue_db[bs.ue_index]; |
332 | | - |
333 | | - u.handle_dl_buffer_state_indication(bs); |
334 | | - if (bs.lcid == LCID_SRB0) { |
335 | | - // Signal SRB0 scheduler with the new SRB0 buffer state. |
336 | | - du_cells[u.get_pcell().cell_index].srb0_sched->handle_dl_buffer_state_indication(bs.ue_index); |
337 | | - } |
338 | | - |
339 | | - // Log event. |
340 | | - ev_logger.enqueue(bs); |
341 | | - |
342 | | - // Report event. |
343 | | - metrics_handler.handle_dl_buffer_state_indication(bs); |
344 | | - }); |
| 393 | + dl_bo_mng->enqueue_rlc_buffer_occupancy_update(bs); |
345 | 394 | } |
346 | 395 |
|
347 | 396 | void ue_event_manager::process_common(slot_point sl, du_cell_index_t cell_index) |
348 | 397 | { |
349 | | - if (last_sl != sl) { |
| 398 | + bool new_slot_detected = last_sl != sl; |
| 399 | + if (new_slot_detected) { |
350 | 400 | // Pop pending common events. |
351 | 401 | common_events.slot_indication(); |
352 | 402 | last_sl = sl; |
@@ -377,6 +427,10 @@ void ue_event_manager::process_common(slot_point sl, du_cell_index_t cell_index) |
377 | 427 | } |
378 | 428 | } |
379 | 429 | } |
| 430 | + |
| 431 | + if (new_slot_detected) { |
| 432 | + dl_bo_mng->slot_indication(); |
| 433 | + } |
380 | 434 | } |
381 | 435 |
|
382 | 436 | void ue_event_manager::process_cell_specific(du_cell_index_t cell_index) |
|
0 commit comments