matanp has submitted this change. ( https://gerrit.osmocom.org/c/osmo-bsc/+/41415?usp=email )
Change subject: handover_decision: Check for connection prerequisites ......................................................................
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(-)
Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved fixeria: Looks good to me, but someone else must approve
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 - - - - - -