aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/pdch_ul_controller.c23
-rw-r--r--src/pdch_ul_controller.h1
-rw-r--r--src/sba.c9
-rw-r--r--tests/ulc/PdchUlcTest.cpp25
-rw-r--r--tests/ulc/PdchUlcTest.ok9
5 files changed, 64 insertions, 3 deletions
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 ===