aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@espeweb.net>2021-02-22 17:20:15 +0100
committerpespin <pespin@sysmocom.de>2021-02-24 13:48:01 +0000
commited2afa3bed4c1b7a2bffae6be7df881de4f976e7 (patch)
treec4d1089fd08ec6f7d1e562b247b6606b2806c0d2 /src
parent50aa492b8527df0724876ed80165cbdeedccb22b (diff)
Support uplink multi-slot allocations
Before this patch, allocate_usf() was implemented to only allocate 1 USF per TBF, regardless of the available ul_slot mask. As a result, only 1 slot at max was allocated to any TBF. That's a pity because usual multislot classes like 12 support up to 2 UL slots per TBF (in common TS with DL). This patch reworks allocate_usf() to allocate as many UL multislots as possible (given mslot class, current USF availability, TFI availability, related DL TBF slots for the same MS, etc.). As a result, it can be seen that AllocTest results change substantially and maximum concurrent TBF allocation drops under some conditions. That happens due to more USFs being reserved (because each TBF has now more UL slots reserved). Hence now USF exhaustion becomes the usual limitation factor as per the number of concurrent TBFs than can be handled per TRX (as opposed to TFIs previously). Some of the biggest limitations in test appear though because really high end multislot classes are used, which can consume high volumes of UL slots (USFs), and which are probably not the most extended devices in the field. Moreover, in general the curren timeslot allocator for a given multislot class will in general try to optimize the DL side gathering most of the possible timeslots there. That means, for instance on ms class 12 (4 Tx, 4Rx, 5 Sum), 4 DL slots and 1 UL slot will still be selected. But in the case where only 3 PDCHs are available, then with this new multi-slot UL support a TBF will reserve 3 DL slots and 2 UL slots, while before this patch it would only taken 1 UL slot instead of 2. This USF exhaustion situation can be improved in the future by parametrizing (VTY command?) the maximum amount of UL slots that a TBF can reserve, making for instance a default value of 2, meaning usual classes can gather up 2 UL timelosts at a time while forbidding high-end hungry classes to gather up to 8 UL timeslots. Another approach would be to dynamically limit the amount of allowed reservable UL timeslots based on current USF reservation load. Related: OS#2282 Change-Id: Id97cc6e3b769511b591b1694549e0dac55227c43
Diffstat (limited to 'src')
-rw-r--r--src/gprs_rlcmac_ts_alloc.cpp45
1 files changed, 23 insertions, 22 deletions
diff --git a/src/gprs_rlcmac_ts_alloc.cpp b/src/gprs_rlcmac_ts_alloc.cpp
index 5f0bcc50..72024239 100644
--- a/src/gprs_rlcmac_ts_alloc.cpp
+++ b/src/gprs_rlcmac_ts_alloc.cpp
@@ -740,39 +740,41 @@ static int tbf_select_slot_set(const gprs_rlcmac_tbf *tbf, const gprs_rlcmac_trx
/*! Allocate USF according to a given UL TS mapping
*
- * N. B: this is legacy implementation which ignores given selected_ul_slots
* \param[in] trx Pointer to TRX object
- * \param[in] tbf Pointer to TBF object
- * \param[in] first_common_ts First TS which is common to both UL and DL
* \param[in] selected_ul_slots set of UL timeslots selected for allocation
* \param[in] dl_slots set of DL timeslots
* \param[out] usf array for allocated USF
- * \returns updated UL TS or negative on error
+ * \returns updated UL TS mask or negative on error
*/
-static int allocate_usf(const gprs_rlcmac_trx *trx, int8_t first_common_ts, uint8_t selected_ul_slots, uint8_t dl_slots,
- int *usf)
+static int allocate_usf(const gprs_rlcmac_trx *trx, uint8_t selected_ul_slots, uint8_t dl_slots,
+ int *usf_list)
{
- int free_usf = -1, ts;
- uint8_t ul_slots = selected_ul_slots;
+ uint8_t ul_slots = selected_ul_slots & dl_slots;
+ unsigned int ts;
- if (first_common_ts >= 0)
- ul_slots = 1 << first_common_ts;
- else
- ul_slots = ul_slots & dl_slots;
+ for (ts = 0; ts < ARRAY_SIZE(trx->pdch); ts++) {
+ const struct gprs_rlcmac_pdch *pdch = &trx->pdch[ts];
+ int8_t free_usf;
- ts = find_least_busy_pdch(trx, GPRS_RLCMAC_UL_TBF, ul_slots, compute_usage_by_num_tbfs, NULL, &free_usf);
+ if (((1 << ts) & ul_slots) == 0)
+ continue;
- if (free_usf < 0 || ts < 0) {
+ free_usf = find_free_usf(pdch->assigned_usf());
+ if (free_usf < 0) {
+ LOGP(DRLCMAC, LOGL_DEBUG,
+ "- Skipping TS %d, because "
+ "no USF available\n", ts);
+ ul_slots &= (~(1 << ts)) & 0xff;
+ continue;
+ }
+ usf_list[ts] = free_usf;
+ }
+
+ if (!ul_slots) {
LOGP(DRLCMAC, LOGL_NOTICE, "No USF available\n");
return -EBUSY;
}
- OSMO_ASSERT(ts >= 0 && ts <= 8);
-
- /* We will stick to that single UL slot, unreserve the others */
- ul_slots = 1 << ts;
- usf[ts] = free_usf;
-
return ul_slots;
}
@@ -920,11 +922,10 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts, GprsMs *ms_, struct gprs_rlcm
dl_slots = rc;
update_slot_counters(dl_slots, reserved_dl_slots, &slotcount, &avail_count);
} else {
- rc = allocate_usf(trx, first_common_ts, rc, dl_slots, usf);
+ rc = allocate_usf(trx, rc, dl_slots, usf);
if (rc < 0)
return rc;
- /* We will stick to that single UL slot, unreserve the others */
ul_slots = rc;
reserved_ul_slots = ul_slots;