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
This commit is contained in:
Pau Espin Pedrol 2021-02-22 17:20:15 +01:00 committed by pespin
parent 50aa492b85
commit ed2afa3bed
4 changed files with 7595 additions and 8759 deletions

View File

@ -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;

View File

@ -738,17 +738,17 @@ static inline void test_a_b_dyn(enum test_mode mode, uint8_t exp_A, uint8_t exp_
static void test_successive_allocations()
{
test_successive_allocation(alloc_algorithm_a, 1, 1, TEST_MODE_UL_AND_DL, 35, "A");
test_successive_allocation(alloc_algorithm_b, 10, 10, TEST_MODE_UL_AND_DL, 32, "B");
test_successive_allocation(alloc_algorithm_b, 12, 12, TEST_MODE_UL_AND_DL, 32, "B");
test_successive_allocation(alloc_algorithm_b, 10, 10, TEST_MODE_UL_AND_DL, 15, "B");
test_successive_allocation(alloc_algorithm_b, 12, 12, TEST_MODE_UL_AND_DL, 15, "B");
test_successive_allocation(alloc_algorithm_b, 1, 12, TEST_MODE_UL_AND_DL, 32, "B");
test_successive_allocation(alloc_algorithm_b, 1, mslot_class_max(), TEST_MODE_UL_AND_DL, 32, "B");
test_successive_allocation(alloc_algorithm_dynamic, 1, mslot_class_max(), TEST_MODE_UL_AND_DL, 35, "dynamic");
test_successive_allocation(alloc_algorithm_b, 1, 12, TEST_MODE_UL_AND_DL, 23, "B");
test_successive_allocation(alloc_algorithm_b, 1, mslot_class_max(), TEST_MODE_UL_AND_DL, 17, "B");
test_successive_allocation(alloc_algorithm_dynamic, 1, mslot_class_max(), TEST_MODE_UL_AND_DL, 17, "dynamic");
test_a_b_dyn(TEST_MODE_DL_AND_UL, 35, 32, 32);
test_a_b_dyn(TEST_MODE_DL_AFTER_UL, 160, 32, 95);
test_a_b_dyn(TEST_MODE_UL_AFTER_DL, 35, 32, 35);
test_a_b_dyn(TEST_MODE_UL_ONLY, 35, 32, 35);
test_a_b_dyn(TEST_MODE_DL_AND_UL, 35, 15, 15);
test_a_b_dyn(TEST_MODE_DL_AFTER_UL, 160, 32, 101);
test_a_b_dyn(TEST_MODE_UL_AFTER_DL, 35, 15, 15);
test_a_b_dyn(TEST_MODE_UL_ONLY, 35, 15, 21);
test_a_b_dyn(TEST_MODE_DL_ONLY, 160, 32, 101);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff