aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/bsc/gsm_data.h3
-rw-r--r--include/osmocom/bsc/gsm_data_shared.h2
-rw-r--r--openbsc/src/libbsc/handover_vty.c17
-rw-r--r--openbsc/tests/handover/handover_test.c36
-rw-r--r--src/libbsc/handover_logic.c16
-rw-r--r--tests/testsuite.at6
6 files changed, 74 insertions, 6 deletions
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index 0928d0262..c966e0506 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/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/include/osmocom/bsc/gsm_data_shared.h b/include/osmocom/bsc/gsm_data_shared.h
index 5ef3ef4ea..36cf6f7b0 100644
--- a/include/osmocom/bsc/gsm_data_shared.h
+++ b/include/osmocom/bsc/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_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/src/libbsc/handover_logic.c b/src/libbsc/handover_logic.c
index 06f968c2b..2a7733f6e 100644
--- a/src/libbsc/handover_logic.c
+++ b/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/tests/testsuite.at b/tests/testsuite.at
index 12a648767..2d5dd98bf 100644
--- a/tests/testsuite.at
+++ b/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
+