diff options
-rw-r--r-- | include/osmocom/bsc/gsm_data.h | 3 | ||||
-rw-r--r-- | include/osmocom/bsc/gsm_data_shared.h | 2 | ||||
-rw-r--r-- | openbsc/src/libbsc/handover_vty.c | 17 | ||||
-rw-r--r-- | openbsc/tests/handover/handover_test.c | 36 | ||||
-rw-r--r-- | src/libbsc/handover_logic.c | 16 | ||||
-rw-r--r-- | tests/testsuite.at | 6 |
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 + |