diff --git a/src/pdch_ul_controller.c b/src/pdch_ul_controller.c index e6e22a20..1ead3e90 100644 --- a/src/pdch_ul_controller.c +++ b/src/pdch_ul_controller.c @@ -128,6 +128,29 @@ int pdch_ulc_get_next_free_rrbp_fn(struct pdch_ulc *ulc, uint32_t fn, uint32_t * return 0; } +/* Get next free (unreserved) FN which is not located in time before "start_fn" */ +uint32_t pdch_ulc_get_next_free_fn(struct pdch_ulc *ulc, uint32_t start_fn) +{ + struct rb_node *node; + struct pdch_ulc_node *it; + int res; + uint32_t check_fn = start_fn; + + for (node = rb_first(&ulc->tree_root); node; node = rb_next(node)) { + it = container_of(node, struct pdch_ulc_node, node); + res = fn_cmp(it->fn, check_fn); + if (res > 0) { /* it->fn AFTER check_fn */ + /* Next reserved FN is passed check_fn, hence it means check_fn is free */ + return check_fn; + } + /* if it->fn < check_fn, simply continue iterating, we want to reach at least check_fn */ + if (res == 0)/* it->fn == fn */ + check_fn = fn_next_block(check_fn); + /* if it->fn < check_fn, simply continue iterating, we want to reach at least check_fn */ + } + return check_fn; +} + static struct pdch_ulc_node *_alloc_node(struct pdch_ulc *ulc, uint32_t fn) { struct pdch_ulc_node *node; diff --git a/src/pdch_ul_controller.h b/src/pdch_ul_controller.h index 731cbe14..5339e90a 100644 --- a/src/pdch_ul_controller.h +++ b/src/pdch_ul_controller.h @@ -71,6 +71,7 @@ int pdch_ulc_reserve_sba(struct pdch_ulc *ulc, struct gprs_rlcmac_sba *sba); bool pdch_ulc_fn_is_free(struct pdch_ulc *ulc, uint32_t fn); int pdch_ulc_get_next_free_rrbp_fn(struct pdch_ulc *ulc, uint32_t fn, uint32_t *poll_fn, unsigned int *rrbp); +uint32_t pdch_ulc_get_next_free_fn(struct pdch_ulc *ulc, uint32_t start_fn); struct pdch_ulc_node *pdch_ulc_get_node(struct pdch_ulc *ulc, uint32_t fn); struct pdch_ulc_node *pdch_ulc_pop_node(struct pdch_ulc *ulc, uint32_t fn); diff --git a/src/sba.c b/src/sba.c index 31268930..ce44fa59 100644 --- a/src/sba.c +++ b/src/sba.c @@ -57,15 +57,18 @@ struct gprs_rlcmac_sba *sba_alloc(void *ctx, struct gprs_rlcmac_pdch *pdch, uint8_t ta) { struct gprs_rlcmac_sba *sba; + uint32_t start_fn; + sba = talloc_zero(ctx, struct gprs_rlcmac_sba); if (!sba) return NULL; + /* TODO: Increase start_fn dynamically based on AGCH queue load in the BTS: */ + start_fn = next_fn(pdch->last_rts_fn, AGCH_START_OFFSET); + sba->pdch = pdch; sba->ta = ta; - - /* TODO: request ULC for next available FN instead of hardcoded AGCH_START_OFFSET */ - sba->fn = next_fn(pdch->last_rts_fn, AGCH_START_OFFSET); + sba->fn = pdch_ulc_get_next_free_fn(pdch->ulc, start_fn); pdch_ulc_reserve_sba(pdch->ulc, sba); return sba; diff --git a/tests/ulc/PdchUlcTest.cpp b/tests/ulc/PdchUlcTest.cpp index 00991012..f0e8dd91 100644 --- a/tests/ulc/PdchUlcTest.cpp +++ b/tests/ulc/PdchUlcTest.cpp @@ -212,6 +212,30 @@ static void test_fn_wrap_around() printf("=== end: %s ===\n", __FUNCTION__); } +static void test_next_free_fn_sba() +{ + printf("=== start: %s ===\n", __FUNCTION__); + struct gprs_rlcmac_bts *bts = bts_alloc(the_pcu, 0); + struct gprs_rlcmac_pdch *pdch = &bts->trx[0].pdch[0]; + struct gprs_rlcmac_sba *sba1, *sba2, *sba3, *sba4; + + pdch->last_rts_fn = 52; + printf("*** ALLOC 1 SBA FN=%" PRIu32 ":\n", pdch->last_rts_fn); + sba1 = sba_alloc(bts, pdch, 0); + print_ulc_nodes(pdch->ulc); + + pdch->last_rts_fn = 65; + printf("*** ALLOC 3 SBA FN=%" PRIu32 ":\n", pdch->last_rts_fn); + sba2 = sba_alloc(bts, pdch, 0); + sba3 = sba_alloc(bts, pdch, 0); + sba4 = sba_alloc(bts, pdch, 0); + print_ulc_nodes(pdch->ulc); + (void)sba1; (void)sba2; (void)sba3; (void)sba4; + + talloc_free(bts); + printf("=== end: %s ===\n", __FUNCTION__); +} + int main(int argc, char **argv) { tall_pcu_ctx = talloc_named_const(NULL, 1, "pdch_ulc test context"); @@ -231,6 +255,7 @@ int main(int argc, char **argv) test_reserve_multiple(); test_fn_wrap_around(); + test_next_free_fn_sba(); talloc_free(the_pcu); return EXIT_SUCCESS; diff --git a/tests/ulc/PdchUlcTest.ok b/tests/ulc/PdchUlcTest.ok index f20fb309..5bab5cc4 100644 --- a/tests/ulc/PdchUlcTest.ok +++ b/tests/ulc/PdchUlcTest.ok @@ -247,3 +247,12 @@ FN=34 type=POLL FN=39 type=POLL *** EXPIRE FN=43: === end: test_fn_wrap_around === +=== start: test_next_free_fn_sba === +*** ALLOC 1 SBA FN=52: +FN=104 type=SBA +*** ALLOC 3 SBA FN=65: +FN=104 type=SBA +FN=117 type=SBA +FN=121 type=SBA +FN=125 type=SBA +=== end: test_next_free_fn_sba ===