summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2013-08-08 13:56:23 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2013-08-08 13:56:23 +0200
commitd29e1beed70b935083f1583e17f0c14dad6703cd (patch)
tree44898859ee136ce7bdcef3deec8f2ddc23f37507
parent47b8fe1ec7cd3f95ef211892b5c3347ff2c2cc5d (diff)
HO: Add option to allow immediate retry of assignment/handover if failed
If a number of retries is configured, the retry is allowed. If it fails more than the number of retries, the penalty timer is started to prevent subsequent retries for the given time. Add test case that will test that handover is blocked after the exact number of handover retries are performed.
-rw-r--r--openbsc/include/openbsc/gsm_data.h3
-rw-r--r--openbsc/include/openbsc/gsm_data_shared.h2
-rw-r--r--openbsc/src/libbsc/handover_logic.c16
-rw-r--r--openbsc/src/libbsc/handover_vty.c17
-rw-r--r--openbsc/tests/handover/handover_test.c36
-rw-r--r--openbsc/tests/testsuite.at6
6 files changed, 74 insertions, 6 deletions
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 0928d0262..c966e0506 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -142,7 +142,8 @@ struct gsm_subscriber_connection {
struct gsm_lchan *secondary_lchan;
struct llist_head assignment_queue;
- /* penalty timers for handover */
+ /* failure count and penalty timers for handover */
+ int ho_failure;
struct llist_head ho_penalty_timers;
/* phone's bearer capabilities */
diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h
index 5ef3ef4ea..36cf6f7b0 100644
--- a/openbsc/include/openbsc/gsm_data_shared.h
+++ b/openbsc/include/openbsc/gsm_data_shared.h
@@ -767,6 +767,8 @@ struct gsm_bts {
unsigned int penalty_ho_fail; /* seconds */
/* penalty time for a cell after assignment failure */
unsigned int penalty_as_fail; /* seconds */
+ /* number of retries, before starting penality timer */
+ unsigned int retries;
} handover;
#endif /* ROLE_BSC */
void *role;
diff --git a/openbsc/src/libbsc/handover_logic.c b/openbsc/src/libbsc/handover_logic.c
index 06f968c2b..2a7733f6e 100644
--- a/openbsc/src/libbsc/handover_logic.c
+++ b/openbsc/src/libbsc/handover_logic.c
@@ -371,6 +371,7 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan)
log_handover(DHO, LOGL_INFO, ho);
LOGPC(DHO, LOGL_INFO, "Handover/Assignment completed\n");
+ new_lchan->conn->ho_failure = 0;
net = new_lchan->ts->trx->bts->network;
osmo_counter_inc(net->stats.handover.completed);
@@ -414,11 +415,16 @@ static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan)
new_bts = ho->new_lchan->ts->trx->bts;
log_handover(DHO, LOGL_NOTICE, ho);
- LOGPC(DHO, LOGL_NOTICE, "Handover/Assignment failed, start penalty timer\n");
-
- add_penalty_timer(old_lchan->conn, new_bts,
- (ho->do_ass) ? old_bts->handover.penalty_as_fail
- : old_bts->handover.penalty_ho_fail);
+ if (old_lchan->conn->ho_failure == old_bts->handover.retries) {
+ LOGPC(DHO, LOGL_NOTICE, "Handover/Assignment failed, start penalty timer\n");
+ old_lchan->conn->ho_failure = 0;
+ add_penalty_timer(old_lchan->conn, new_bts,
+ (ho->do_ass) ? old_bts->handover.penalty_as_fail
+ : old_bts->handover.penalty_ho_fail);
+ } else {
+ LOGPC(DHO, LOGL_NOTICE, "Handover/Assignment failed, trying again.\n");
+ old_lchan->conn->ho_failure++;
+ }
osmo_counter_inc(net->stats.handover.failed);
diff --git a/openbsc/src/libbsc/handover_vty.c b/openbsc/src/libbsc/handover_vty.c
index ee449e9f3..69509a6de 100644
--- a/openbsc/src/libbsc/handover_vty.c
+++ b/openbsc/src/libbsc/handover_vty.c
@@ -95,6 +95,8 @@ void config_write_bts_handover(struct vty *vty, struct gsm_bts *bts)
bts->handover.penalty_ho_fail, VTY_NEWLINE);
vty_out(vty, " handover penalty assignment failure %u%s",
bts->handover.penalty_as_fail, VTY_NEWLINE);
+ vty_out(vty, " handover retries %u%s",
+ bts->handover.retries, VTY_NEWLINE);
}
}
@@ -484,6 +486,20 @@ DEFUN(cfg_bts_ho_penalty_as_fail, cfg_bts_ho_penalty_as_fail_cmd,
return CMD_SUCCESS;
}
+DEFUN(cfg_bts_ho_retries, cfg_bts_ho_retries_cmd,
+ "handover retries <0-9>",
+ HANDOVER_STR
+ "Number of immediate retries, if handover/assignment fails\n"
+ "Retries\n")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 0, 1))
+ return CMD_WARNING;
+ bts->handover.retries = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
void bsc_vty_init_handover(void)
{
install_element(GSMNET_NODE, &cfg_net_ho_algorithm_cmd);
@@ -507,5 +523,6 @@ void bsc_vty_init_handover(void)
install_element(BTS_NODE, &cfg_bts_ho_penalty_max_dist_cmd);
install_element(BTS_NODE, &cfg_bts_ho_penalty_ho_fail_cmd);
install_element(BTS_NODE, &cfg_bts_ho_penalty_as_fail_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_retries_cmd);
}
diff --git a/openbsc/tests/handover/handover_test.c b/openbsc/tests/handover/handover_test.c
index 1e0d998a5..4557b6500 100644
--- a/openbsc/tests/handover/handover_test.c
+++ b/openbsc/tests/handover/handover_test.c
@@ -1121,6 +1121,33 @@ static char *test_case_26[] = {
NULL
};
+static char *test_case_27[] = {
+ "2",
+
+ "Only after maximum allowed retries, start penalty timer\n\n"
+ "The MS will try to handover to a better cell, but this will fail.\n"
+ "The handover is performed again and fails again. After this retry,\n"
+ "the handover is not performed again, because penalty timer is\n"
+ "running.\n",
+
+ "create-bts", "2",
+ "ho-retries", "0", "1",
+ "create-ms", "0", "TCH/F", "AMR",
+ "meas-rep", "0", "20","0", "1","0","30",
+ "expect-chan", "1", "1",
+ "ack-chan",
+ "expect-ho", "0", "1",
+ "ho-failed",
+ "meas-rep", "0", "20","0", "1","0","30",
+ "expect-chan", "1", "1",
+ "ack-chan",
+ "expect-ho", "0", "1",
+ "ho-failed",
+ "meas-rep", "0", "20","0", "1","0","30",
+ "expect-no-chan",
+ NULL
+};
+
static char **test_cases[] = {
test_case_0,
test_case_1,
@@ -1149,6 +1176,7 @@ static char **test_cases[] = {
test_case_24,
test_case_25,
test_case_26,
+ test_case_27,
NULL
};
@@ -1240,6 +1268,14 @@ int main(int argc, char **argv)
atoi(test_case[2]);
test_case += 3;
} else
+ if (!strcmp(*test_case, "ho-retries")) {
+ fprintf(stderr, "- Set number of handover/assignment "
+ "retries at BTS %s to %s\n", test_case[1],
+ test_case[2]);
+ bts[atoi(test_case[1])]->handover.retries =
+ atoi(test_case[2]);
+ test_case += 3;
+ } else
if (!strcmp(*test_case, "afs-rxlev-improve")) {
fprintf(stderr, "- Set afs RX level improvement at "
"BTS %s to %s\n", test_case[1], test_case[2]);
diff --git a/openbsc/tests/testsuite.at b/openbsc/tests/testsuite.at
index 12a648767..2d5dd98bf 100644
--- a/openbsc/tests/testsuite.at
+++ b/openbsc/tests/testsuite.at
@@ -222,3 +222,9 @@ cat $abs_srcdir/handover/handover_test.ok > expout
AT_CHECK([$abs_top_builddir/tests/handover/handover_test 26], [], [expout], [ignore])
AT_CLEANUP
+AT_SETUP([handover test 27])
+AT_KEYWORDS([handover])
+cat $abs_srcdir/handover/handover_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/handover/handover_test 27], [], [expout], [ignore])
+AT_CLEANUP
+