Move out of alloc_algo code modifying the data model
This way the alloc_algo() becomes idempotent, simplifying implementation
of new alloc_algos as well as rolling back if allocation fails (for
instance because some resource is exhausted at the time).
For now the code applying the results is moved to tbf::alloc_algo(), but
it will eventually get out of tbf code, so that the MS object is
responsible for running it. As a result, there's no even need to create
TBF object before trying to allocate resources, which will help furher in
rollback operations described above.
Change-Id: I5ffd00f5f80bde4b73b78db44896f65e70e12b20
diff --git a/src/alloc_algo.cpp b/src/alloc_algo.cpp
index bc44cbf..c026590 100644
--- a/src/alloc_algo.cpp
+++ b/src/alloc_algo.cpp
@@ -214,29 +214,6 @@
return min_ts;
}
-static void attach_tbf_to_pdch(struct gprs_rlcmac_pdch *pdch,
- struct gprs_rlcmac_tbf *tbf)
-{
- if (tbf->pdch[pdch->ts_no])
- tbf->pdch[pdch->ts_no]->detach_tbf(tbf);
-
- tbf->pdch[pdch->ts_no] = pdch;
- pdch->attach_tbf(tbf);
-}
-
-static void assign_uplink_tbf_usf(struct gprs_rlcmac_pdch *pdch, struct gprs_rlcmac_ul_tbf *tbf, uint8_t tfi, int8_t usf)
-{
- tbf->m_tfi = tfi;
- tbf->m_usf[pdch->ts_no] = usf;
- attach_tbf_to_pdch(pdch, tbf);
-}
-
-static void assign_dlink_tbf(struct gprs_rlcmac_pdch *pdch, struct gprs_rlcmac_dl_tbf *tbf, uint8_t tfi)
-{
- tbf->m_tfi = tfi;
- attach_tbf_to_pdch(pdch, tbf);
-}
-
static int find_trx(const struct alloc_resources_req *req)
{
unsigned trx_no;
@@ -331,11 +308,12 @@
* Assign single slot for uplink and downlink
*
* \param[in] req Contains all the requested params
+ * \param[out] res The resolution/response for the allocation request
* \returns negative error code or 0 on success
*/
-int alloc_algorithm_a(const struct alloc_resources_req *req)
+int alloc_algorithm_a(const struct alloc_resources_req *req,
+ struct alloc_resources_res *res)
{
- struct gprs_rlcmac_pdch *pdch;
int ts = -1;
uint8_t ul_slots, dl_slots;
int trx_no;
@@ -388,26 +366,15 @@
return -EBUSY;
}
- pdch = &trx->pdch[ts];
+ res->trx = trx;
+ res->first_common_ts = &trx->pdch[ts];
+ res->reserved_ul_slots = 1 << ts;
+ res->reserved_dl_slots = 1 << ts;
+ res->ass_slots_mask = 1 << ts;
+ res->upgrade_to_multislot = false;
+ res->tfi = tfi;
+ res->usf[ts] = usf;
- /* The allocation will be successful, so the system state and tbf/ms
- * may be modified from now on. */
- if (req->direction == GPRS_RLCMAC_UL_TBF) {
- struct gprs_rlcmac_ul_tbf *ul_tbf = tbf_as_ul_tbf(req->tbf);
- LOGPSL(req, LOGL_DEBUG, "Assign uplink TS=%d TFI=%d USF=%d\n", ts, tfi, usf);
- assign_uplink_tbf_usf(pdch, ul_tbf, tfi, usf);
- } else {
- struct gprs_rlcmac_dl_tbf *dl_tbf = tbf_as_dl_tbf(req->tbf);
- LOGPSL(req, LOGL_DEBUG, "Assign downlink TS=%d TFI=%d\n", ts, tfi);
- assign_dlink_tbf(pdch, dl_tbf, tfi);
- }
-
- req->tbf->trx = trx;
- /* the only one TS is the common TS */
- ms_set_reserved_slots(req->ms, trx, 1 << ts, 1 << ts);
- ms_set_first_common_ts(req->ms, pdch);
-
- req->tbf->upgrade_to_multislot = false;
bts_do_rate_ctr_inc(req->bts, CTR_TBF_ALLOC_ALGO_A);
return 0;
}
@@ -766,76 +733,17 @@
return ul_slots;
}
-/*! Update MS' reserved timeslots
- *
- * \param[in,out] trx Pointer to TRX struct
- * \param[in,out] ms_ Pointer to MS object
- * \param[in] tbf_ Pointer to TBF struct
- * \param[in] res_ul_slots Newly reserved UL slots
- * \param[in] res_dl_slots Newly reserved DL slots
- */
-static void update_ms_reserved_slots(gprs_rlcmac_trx *trx, GprsMs *ms, uint8_t res_ul_slots, uint8_t res_dl_slots)
-{
- if (res_ul_slots == ms_reserved_ul_slots(ms) && res_dl_slots == ms_reserved_dl_slots(ms))
- return;
-
- /* The reserved slots have changed, update the MS */
- ms_set_reserved_slots(ms, trx, res_ul_slots, res_dl_slots);
-}
-
-/*! Assign given UL timeslots to UL TBF
- *
- * \param[in,out] ul_tbf Pointer to UL TBF struct
- * \param[in,out] trx Pointer to TRX object
- * \param[in] ul_slots Set of slots to be assigned
- * \param[in] tfi selected TFI
- * \param[in] usf selected USF
- */
-static void assign_ul_tbf_slots(struct gprs_rlcmac_ul_tbf *ul_tbf, gprs_rlcmac_trx *trx, uint8_t ul_slots, int tfi,
- int *usf)
-{
- uint8_t ts;
-
- for (ts = 0; ts < 8; ts++) {
- if (!(ul_slots & (1 << ts)))
- continue;
-
- OSMO_ASSERT(usf[ts] >= 0);
-
- LOGP(DRLCMAC, LOGL_DEBUG, "- Assigning UL TS %u\n", ts);
- assign_uplink_tbf_usf(&trx->pdch[ts], ul_tbf, tfi, usf[ts]);
- }
-}
-
-/*! Assign given DL timeslots to DL TBF
- *
- * \param[in,out] dl_tbf Pointer to DL TBF struct
- * \param[in,out] trx Pointer to TRX object
- * \param[in] ul_slots Set of slots to be assigned
- * \param[in] tfi selected TFI
- */
-static void assign_dl_tbf_slots(struct gprs_rlcmac_dl_tbf *dl_tbf, gprs_rlcmac_trx *trx, uint8_t dl_slots, int tfi)
-{
- uint8_t ts;
-
- for (ts = 0; ts < 8; ts++) {
- if (!(dl_slots & (1 << ts)))
- continue;
-
- LOGP(DRLCMAC, LOGL_DEBUG, "- Assigning DL TS %u\n", ts);
- assign_dlink_tbf(&trx->pdch[ts], dl_tbf, tfi);
- }
-}
-
/*! Slot Allocation: Algorithm B
*
* Assign as many downlink slots as possible.
* Assign one uplink slot. (With free USF)
*
* \param[in] req Contains all the requested params
+ * \param[out] res The resolution/response for the allocation request
* \returns negative error code or 0 on success
*/
-int alloc_algorithm_b(const struct alloc_resources_req *req)
+int alloc_algorithm_b(const struct alloc_resources_req *req,
+ struct alloc_resources_res *res)
{
uint8_t dl_slots;
uint8_t ul_slots;
@@ -845,15 +753,18 @@
uint8_t slotcount = 0;
uint8_t reserve_count = 0, trx_no;
int first_ts;
- int usf[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
int rc;
int tfi;
+ unsigned int i;
gprs_rlcmac_trx *trx;
char slot_info[9] = { 0 };
struct gprs_rlcmac_pdch *first_common_ts = ms_first_common_ts(req->ms);
LOGPAL(req, "B", LOGL_DEBUG, "Alloc start\n");
+ for (i = 0; i < ARRAY_SIZE(res->usf); i++)
+ res->usf[i] = -1;
+
/* Step 1: Get current state from the MS object */
reserved_dl_slots = ms_reserved_dl_slots(req->ms);
@@ -889,7 +800,7 @@
dl_slots = rc;
count_slots(dl_slots, reserved_dl_slots, &slotcount, &reserve_count);
} else {
- rc = allocate_usf(trx, rc, dl_slots, usf);
+ rc = allocate_usf(trx, rc, dl_slots, &res->usf[0]);
if (rc < 0)
return rc;
@@ -912,30 +823,27 @@
}
first_common_ts = &trx->pdch[first_common_tn];
+ res->trx = trx;
+ res->first_common_ts = first_common_ts;
+ res->reserved_ul_slots = reserved_ul_slots;
+ res->reserved_dl_slots = reserved_dl_slots;
+ res->tfi = tfi;
+ /* res->usf is already filled in above */
if (req->single && slotcount) {
- req->tbf->upgrade_to_multislot = (reserve_count > slotcount);
+ res->upgrade_to_multislot = (reserve_count > slotcount);
LOGPAL(req, "B", LOGL_INFO, "using single slot at TS %d\n", first_ts);
} else {
- req->tbf->upgrade_to_multislot = false;
+ res->upgrade_to_multislot = false;
LOGPAL(req, "B", LOGL_INFO, "using %d slots\n", slotcount);
}
ts_format(slot_info, dl_slots, ul_slots);
LOGP(DRLCMAC, LOGL_DEBUG, "- Available DL/UL slots: (TS=0)\"%s\"(TS=7)\n", slot_info);
- /* The allocation will be successful, so the system state and tbf/ms
- * may be modified from now on. */
-
- /* Step 4: Update MS and TBF and really allocate the resources */
-
- update_ms_reserved_slots(trx, req->ms, reserved_ul_slots, reserved_dl_slots);
- ms_set_first_common_ts(req->ms, first_common_ts);
- req->tbf->trx = trx;
-
if (req->direction == GPRS_RLCMAC_DL_TBF)
- assign_dl_tbf_slots(tbf_as_dl_tbf(req->tbf), trx, dl_slots, tfi);
+ res->ass_slots_mask = dl_slots;
else
- assign_ul_tbf_slots(tbf_as_ul_tbf(req->tbf), trx, ul_slots, tfi, usf);
+ res->ass_slots_mask = ul_slots;
bts_do_rate_ctr_inc(req->bts, CTR_TBF_ALLOC_ALGO_B);
@@ -951,9 +859,11 @@
* goal is to provide the highest possible bandwidth per MS.
*
* \param[in] req Contains all the requested params
+ * \param[out] res The resolution/response for the allocation request
* \returns negative error code or 0 on success
*/
-int alloc_algorithm_dynamic(const struct alloc_resources_req *req)
+int alloc_algorithm_dynamic(const struct alloc_resources_req *req,
+ struct alloc_resources_res *res)
{
int rc;
@@ -965,7 +875,7 @@
}
if (!req->bts->multislot_disabled) {
- rc = alloc_algorithm_b(req);
+ rc = alloc_algorithm_b(req, res);
if (rc >= 0)
return rc;
@@ -974,7 +884,7 @@
req->bts->multislot_disabled = 1;
}
- return alloc_algorithm_a(req);
+ return alloc_algorithm_a(req, res);
}
int gprs_alloc_max_dl_slots_per_ms(const struct gprs_rlcmac_bts *bts, uint8_t ms_class)