matanp submitted this change.
handover_decision: Check for connection prerequisites
Before this fix, a handover could be started while
subscriber doesn't have a connection or while an initial
assignment is stiil going.
In some cases, it would cause the assert in handover_request
to fail.
Change-Id: I37314bdadd306ea96963d020b7c5372323e4640d
---
M src/osmo-bsc/handover_decision.c
M tests/handover/handover_test.c
M tests/handover/handover_tests.ok
A tests/handover/test_ho_1_rxqual_before_connection.ho_vty
4 files changed, 78 insertions(+), 5 deletions(-)
diff --git a/src/osmo-bsc/handover_decision.c b/src/osmo-bsc/handover_decision.c
index 2fb466c..2cb12a3 100644
--- a/src/osmo-bsc/handover_decision.c
+++ b/src/osmo-bsc/handover_decision.c
@@ -234,6 +234,20 @@
if (mr->num_cell > 0 && mr->num_cell < 7)
process_meas_neigh(mr);
+ /* check for ongoing handover/assignment */
+ if (!mr->lchan->conn) {
+ LOGPHOLCHAN(mr->lchan, LOGL_ERROR, "Skipping, No subscriber connection???\n");
+ return;
+ }
+ if (mr->lchan->conn->assignment.new_lchan) {
+ LOGPHOLCHAN(mr->lchan, LOGL_INFO, "Skipping, Initial Assignment is still ongoing\n");
+ return;
+ }
+ if (mr->lchan->conn->ho.fi) {
+ LOGPHOLCHAN(mr->lchan, LOGL_INFO, "Skipping, Handover still ongoing\n");
+ return;
+ }
+
av_rxlev = get_meas_rep_avg(mr->lchan, TDMA_MEAS_FIELD_RXLEV, TDMA_MEAS_DIR_DL, TDMA_MEAS_SET_AUTO,
ho_get_hodec1_rxlev_avg_win(bts->ho));
diff --git a/tests/handover/handover_test.c b/tests/handover/handover_test.c
index e4c7873..7740f0b 100644
--- a/tests/handover/handover_test.c
+++ b/tests/handover/handover_test.c
@@ -437,7 +437,7 @@
osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_A_CONN_CFM, NULL);
}
-struct gsm_lchan *lchan_act(struct gsm_lchan *lchan, int full_rate, const char *codec)
+struct gsm_lchan *lchan_act_without_conn(struct gsm_lchan *lchan, int full_rate, const char *codec)
{
/* serious hack into osmo_fsm */
lchan->fi->state = LCHAN_ST_ESTABLISHED;
@@ -455,7 +455,6 @@
LOG_LCHAN(lchan, LOGL_DEBUG, "activated by handover_test.c\n");
- create_conn(lchan);
if (!strcasecmp(codec, "FR") && full_rate)
lchan->current_ch_mode_rate.chan_mode = GSM48_CMODE_SPEECH_V1;
else if (!strcasecmp(codec, "HR") && !full_rate)
@@ -470,6 +469,15 @@
exit(EXIT_FAILURE);
}
+ chan_counts_ts_update(lchan->ts);
+
+ return lchan;
+}
+
+struct gsm_lchan *lchan_act(struct gsm_lchan *lchan, int full_rate, const char *codec)
+{
+ lchan_act_without_conn(lchan, full_rate, codec);
+ create_conn(lchan);
lchan->conn->codec_list = (struct gsm0808_speech_codec_list){
.codec = {
{ .fi=true, .type=GSM0808_SCT_FR1, },
@@ -480,9 +488,6 @@
},
.len = 5,
};
-
- chan_counts_ts_update(lchan->ts);
-
return lchan;
}
@@ -500,6 +505,20 @@
return lchan_act(lchan, full_rate, codec);
}
+struct gsm_lchan *create_lchan_without_conn(struct gsm_bts *bts, int full_rate, const char *codec)
+{
+ struct gsm_lchan *lchan;
+
+ lchan = lchan_select_by_type(bts, (full_rate) ? GSM_LCHAN_TCH_F : GSM_LCHAN_TCH_H,
+ SELECT_FOR_HANDOVER, NULL);
+ if (!lchan) {
+ fprintf(stderr, "No resource for lchan\n");
+ exit(EXIT_FAILURE);
+ }
+
+ return lchan_act_without_conn(lchan, full_rate, codec);
+}
+
static void lchan_release_ack(struct gsm_lchan *lchan)
{
if (!lchan->fi || lchan->fi->state != LCHAN_ST_WAIT_BEFORE_RF_RELEASE)
@@ -975,6 +994,30 @@
return CMD_SUCCESS;
}
+DEFUN(create_empty_lchan, create_empty_lchan_cmd,
+ "create-empty-lchan bts <0-999> (TCH/F|TCH/H) (AMR|HR|EFR)",
+ "Create channel using the next free matching lchan on a given BTS, simulate not yet connected MS\n"
+ "BTS index to create on\n"
+ "lchan type to select\n"
+ "codec\n")
+{
+ const char *bts_nr_str = argv[0];
+ const char *tch_type = argv[1];
+ const char *codec = argv[2];
+ struct gsm_lchan *lchan;
+ VTY_ECHO();
+ fprintf(stderr, "- Creating mobile at BTS %s on "
+ "%s with %s codec\n", bts_nr_str, tch_type, codec);
+ lchan = create_lchan_without_conn(bts_by_num_str(bts_nr_str),
+ !strcmp(tch_type, "TCH/F"), codec);
+ if (!lchan) {
+ fprintf(stderr, "Failed to create lchan!\n");
+ return CMD_WARNING;
+ }
+ fprintf(stderr, " * New channel is at %s\n", gsm_lchan_name(lchan));
+ return CMD_SUCCESS;
+}
+
struct meas_rep_data {
int argc;
const char **argv;
@@ -1527,6 +1570,7 @@
install_element(CONFIG_NODE, &create_n_bts_cmd);
install_element(CONFIG_NODE, &create_bts_cmd);
install_element(CONFIG_NODE, &create_ms_cmd);
+ install_element(CONFIG_NODE, &create_empty_lchan_cmd);
install_element(CONFIG_NODE, &meas_rep_cmd);
install_element(CONFIG_NODE, &meas_rep_repeat_cmd);
install_element(CONFIG_NODE, &meas_rep_repeat_bspower_cmd);
diff --git a/tests/handover/handover_tests.ok b/tests/handover/handover_tests.ok
index 0424181..d3bf030 100644
--- a/tests/handover/handover_tests.ok
+++ b/tests/handover/handover_tests.ok
@@ -33,6 +33,7 @@
pass test_dyn_ts_favor_half_used_tch_h_as_target.ho_vty
pass test_dyn_ts_favor_moving_half_used_tch_h.ho_vty
pass test_dyn_ts_favor_static_ts_as_target.ho_vty
+pass test_ho_1_rxqual_before_connection.ho_vty
pass test_ho_to_better_cell.ho_vty
pass test_ho_to_better_cell_2.ho_vty
pass test_hysteresis.ho_vty
diff --git a/tests/handover/test_ho_1_rxqual_before_connection.ho_vty b/tests/handover/test_ho_1_rxqual_before_connection.ho_vty
new file mode 100644
index 0000000..6dd2737
--- /dev/null
+++ b/tests/handover/test_ho_1_rxqual_before_connection.ho_vty
@@ -0,0 +1,14 @@
+# Do not try to handover (algorithm 1) if connection is not yet created.
+
+create-n-bts 1
+
+network
+ bts 0
+ handover algorithm 1
+ neighbor-list mode manual-si5
+ neighbor-list add arfcn 100
+ si5 neighbor-list add arfcn 100
+
+create-empty-lchan bts 0 TCH/F AMR
+meas-rep repeat 3 lchan 0 0 1 0 rxlev 0 rxqual 6 ta 0 neighbors 30
+expect-ts-use trx 0 0 states * TCH/F - - - - - -
To view, visit change 41415. To unsubscribe, or for help writing mail filters, visit settings.