neels has submitted this change and it was merged. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/14765 )
Change subject: bsc: add TC_ho_neighbor_config_1 thru _7 ...................................................................... bsc: add TC_ho_neighbor_config_1 thru _7 Add tests to play through various neighbor configurations. Tests will pass as soon as osmo-bsc I29bca59ab232eddc74e0d4698efb9c9992443983 is merged. Add RSL2 to allow triggering handover to BTS 2. Adjust osmo-bsc.cfg to match the new tests. Also applied in docker-playground I1c57a04747f5ec004ccf4657954dcb0b003c24fc. - Actually enable handover. - Add bts 3 Depends: osmo-bsc I8623ab581639e9f8af6a9ff1eca990518d1b1211 ('no neighbors') Related: OS#4056 Change-Id: Ia4ba0e75abd3d45a3422b2525e5f938cdc5a04cc --- M bsc/BSC_Tests.ttcn M bsc/osmo-bsc.cfg M library/RSL_Emulation.ttcn 3 files changed, 396 insertions(+), 1 deletion(-) Approvals: laforge: Looks good to me, but someone else must approve neels: Looks good to me, approved pespin: Looks good to me, but someone else must approve Jenkins Builder: Verified diff --git a/bsc/BSC_Tests.ttcn b/bsc/BSC_Tests.ttcn index 44a9172..4497a2e 100644 --- a/bsc/BSC_Tests.ttcn +++ b/bsc/BSC_Tests.ttcn @@ -1719,6 +1719,10 @@ connect(vc_conn:RSL1, bts[1].rsl.vc_RSL:CLIENT_PT); connect(vc_conn:RSL1_PROC, bts[1].rsl.vc_RSL:RSL_PROC); } + if (isvalue(bts[2])) { + connect(vc_conn:RSL2, bts[2].rsl.vc_RSL:CLIENT_PT); + connect(vc_conn:RSL2_PROC, bts[2].rsl.vc_RSL:RSL_PROC); + } connect(vc_conn:BSSAP, g_bssap.vc_RAN:CLIENT); connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT); connect(vc_conn:MGCP_MULTI, vc_MGCP:MGCP_CLIENT_MULTI); @@ -2837,6 +2841,11 @@ f_vty_transceive(BSCVTY, cmd & suffix); } +/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always + * translates that to a target ARFCN+BSIC first. See bsc_vty.c trigger_ho_or_as(), which puts the selected BTS' neighbor + * ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a + * viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC + * pair, not really to a specific BTS number. */ private function f_vty_handover(integer bts_nr, integer trx_nr, RslChannelNr chan_nr, integer new_bts_nr) runs on MSC_ConnHdlr { @@ -3587,6 +3596,353 @@ vc_conn.done; } +type record of charstring Commands; + +private function f_bts_0_cfg(Commands cmds := {}) runs on MSC_ConnHdlr +{ + f_vty_enter_cfg_bts(BSCVTY, 0); + for (var integer i := 0; i < sizeof(cmds); i := i+1) { + f_vty_transceive(BSCVTY, cmds[i]); + } + f_vty_transceive(BSCVTY, "end"); +} + +private function f_probe_for_handover(charstring log_label, + charstring log_descr, + charstring handover_vty_cmd, + boolean expect_handover, + boolean is_inter_bsc_handover := false) +runs on MSC_ConnHdlr +{ + var RSL_Message rsl; + + var charstring log_msg := " (expecting handover)" + if (not expect_handover) { + log_msg := " (expecting NO handover)"; + } + log("f_probe_for_handover starting: " & log_label & ": " & log_descr & log_msg); + f_vty_transceive(BSCVTY, handover_vty_cmd); + + /* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target + * lchans to be established on bts 1 or bts 2. */ + f_rslem_suspend(RSL1_PROC); + f_rslem_suspend(RSL2_PROC); + + timer T := 2.0; + T.start; + + alt { + [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl { + var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload); + log("Rx L3 from net: ", l3); + if (ischosen(l3.msgs.rrm.handoverCommand)) { + var RslChannelNr new_chan_nr; + var GsmArfcn arfcn; + f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2, + new_chan_nr, arfcn); + log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn); + log(l3.msgs.rrm.handoverCommand); + + /* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really + * matter on which BTS it really is, we're not going to follow through an entire handover + * anyway. */ + f_rslem_register(0, new_chan_nr, RSL1_PROC); + f_rslem_resume(RSL1_PROC); + f_rslem_register(0, new_chan_nr, RSL2_PROC); + f_rslem_resume(RSL2_PROC); + + if (expect_handover and not is_inter_bsc_handover) { + setverdict(pass); + log("f_probe_for_handover(" & log_label & "): Got RSL Handover Command as expected."); + } else { + setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got RSL Handover Command. " + & log_label & ": " & log_descr); + } + + log("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure."); + /* osmo-bsc has triggered Handover. That's all we need to know for this test, reply with + * Handover Failure. */ + f_rsl_send_l3(ts_RRM_HandoverFailure('00'O)); + + /* target BTS is told to release lchan again; don't care which BTS nor what messages. */ + f_sleep(0.5); + RSL1.clear; + RSL2.clear; + log("f_probe_for_handover(" & log_label & "): done (got RSL Handover Command)"); + break; + } else { + repeat; + } + } + [] BSSAP.receive(tr_BSSMAP_HandoverRequired) { + if (expect_handover and is_inter_bsc_handover) { + setverdict(pass); + log("f_probe_for_handover(" & log_label & "): Got BSSMAP Handover Required as expected."); + } else { + setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected none, but got BSSMAP Handover Required. " + & log_label & ": " & log_descr); + } + + log("f_probe_for_handover(" & log_label & "): done (got BSSMAP Handover Required)"); + + /* Note: f_tc_ho_neighbor_config_start() sets T7, the timeout for BSSMAP Handover Required, to + * 1 second. There is no legal way to quickly abort a handover after a BSSMAP Handover Required, + * setting a short timeout and waiting is the only way. */ + log("f_probe_for_handover(" & log_label & "): waiting for inter-BSC HO to time out..."); + f_sleep(1.5); + log("f_probe_for_handover(" & log_label & "): ...done"); + + break; + } + [] T.timeout { + if (expect_handover) { + setverdict(fail, "f_probe_for_handover(" & log_label & "): Expected Handover, but got none. " + & log_label & ": " & log_descr); + } else { + setverdict(pass); + log("f_probe_for_handover(" & log_label & "): Got no Handover, as expected."); + } + log("f_probe_for_handover(" & log_label & "): done (got no Handover)"); + break; + } + } + + f_rslem_resume(RSL1_PROC); + f_rslem_resume(RSL2_PROC); + f_sleep(3.0); + RSL.clear; + + log("f_probe_for_handover(" & log_label & "): done clearing"); +} + +/* Test the effect of various neighbor configuration scenarios: + * + * To avoid complexity, block off any actual handover operation, and always remain on the lchan at bts 0. + * Reconfigure the neighbors for bts 0, trigger a Handover, and probe whether osmo-bsc does or doesn't start HO. + */ +private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr { + g_pars := f_gen_test_hdlr_pars(); + var template PDU_BSSAP exp_compl := f_gen_exp_compl(); + var PDU_BSSAP ass_cmd := f_gen_ass_req(); + const OCT8 kc := '0001020304050607'O; + + ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType); + ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR})); + + /* Establish lchan at bts 0 */ + f_establish_fully(ass_cmd, exp_compl); + + /* Shorten the inter-BSC Handover timeout, to not wait so long for inter-BSC Handovers */ + f_vty_enter_cfg_network(BSCVTY); + f_vty_transceive(BSCVTY, "timer T7 1"); + f_vty_transceive(BSCVTY, "end"); +} + +private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr { + f_tc_ho_neighbor_config_start(); + + /* + * bts 0 ARFCN 871 BSIC 10 + * bts 1 ARFCN 871 BSIC 11 + * bts 2 ARFCN 871 BSIC 12 + * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC + */ + + log("f_tc_ho_neighbor_config: 1. No 'neighbor' config"); + f_bts_0_cfg({"no neighbors"}); + f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)", + "handover any to arfcn 871 bsic 11", + true); + + f_probe_for_handover("1.b", "HO to unknown cell does not start", + "handover any to arfcn 13 bsic 39", + false); + + f_probe_for_handover("1.c", "HO to 871-12 is ambiguous = error", + "handover any to arfcn 871 bsic 12", + false); + + f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)", + "handover any to arfcn 871 bsic 11", + true); +} +private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr { + f_tc_ho_neighbor_config_start(); + + /* + * bts 0 ARFCN 871 BSIC 10 + * bts 1 ARFCN 871 BSIC 11 + * bts 2 ARFCN 871 BSIC 12 + * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC + */ + + log("f_tc_ho_neighbor_config: 2. explicit local neighbor: 'neighbor bts 1'"); + f_bts_0_cfg({"neighbor bts 1"}); + f_sleep(0.5); + + f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor", + "handover any to arfcn 871 bsic 11", + true); + + f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor", + "handover any to arfcn 871 bsic 12", + false); +} +private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr { + f_tc_ho_neighbor_config_start(); + + /* + * bts 0 ARFCN 871 BSIC 10 + * bts 1 ARFCN 871 BSIC 11 + * bts 2 ARFCN 871 BSIC 12 + * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC + */ + + log("f_tc_ho_neighbor_config: 3. explicit local neighbor: 'neighbor bts 2'"); + f_bts_0_cfg({"no neighbors", "neighbor bts 2"}); + f_sleep(0.5); + + f_probe_for_handover("3.a", "HO to bts 1 doesn't work, not listed as neighbor", + "handover any to arfcn 871 bsic 11", + false); + f_probe_for_handover("3.b", "HO to bts 2 works, explicitly listed as neighbor; no ambiguity because bts 3 is not listed as neighbor", + "handover any to arfcn 871 bsic 12", + true); +} +private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr { + f_tc_ho_neighbor_config_start(); + + /* + * bts 0 ARFCN 871 BSIC 10 + * bts 1 ARFCN 871 BSIC 11 + * bts 2 ARFCN 871 BSIC 12 + * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC + */ + + log("f_tc_ho_neighbor_config: 4. explicit remote neighbor: 'neighbor lac 99 arfcn 123 bsic 45'"); + f_bts_0_cfg({"no neighbors", "neighbor lac 99 arfcn 123 bsic 45"}); + f_sleep(0.5); + + f_probe_for_handover("4.a", "HO to bts 1 doesn't work, not listed as neighbor", + "handover any to arfcn 871 bsic 11", + false); + f_probe_for_handover("4.b", "HO to bts 2 doesn't work, not listed as neighbor", + "handover any to arfcn 871 bsic 12", + false); + f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO", + "handover any to arfcn 123 bsic 45", + true, true); +} +private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr { + f_tc_ho_neighbor_config_start(); + + /* + * bts 0 ARFCN 871 BSIC 10 + * bts 1 ARFCN 871 BSIC 11 + * bts 2 ARFCN 871 BSIC 12 + * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC + */ + + log("f_tc_ho_neighbor_config: 5. explicit remote neighbor re-using ARFCN+BSIC: 'neighbor lac 99 arfcn 871 bsic 12'"); + f_bts_0_cfg({"no neighbors", "neighbor lac 99 arfcn 871 bsic 12"}); + f_sleep(0.5); + + f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)", + "handover any to arfcn 871 bsic 12", + true, true); +} +private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr { + f_tc_ho_neighbor_config_start(); + + /* + * bts 0 ARFCN 871 BSIC 10 + * bts 1 ARFCN 871 BSIC 11 + * bts 2 ARFCN 871 BSIC 12 + * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC + */ + + log("f_tc_ho_neighbor_config: 6. config error: explicit local and remote neighbors with ambiguous ARFCN+BSIC:" + & " 'neighbor bts 2; neighbor lac 99 arfcn 871 bsic 12'"); + f_bts_0_cfg({"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 871 bsic 12"}); + f_sleep(0.5); + + f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error", + "handover any to arfcn 871 bsic 12", + false); +} +private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr { + f_tc_ho_neighbor_config_start(); + + /* + * bts 0 ARFCN 871 BSIC 10 + * bts 1 ARFCN 871 BSIC 11 + * bts 2 ARFCN 871 BSIC 12 + * bts 3 ARFCN 871 BSIC 12 serves as ambiguity for bts 2, re-using the ARFCN+BSIC + */ + + log("f_tc_ho_neighbor_config: 7. explicit local and remote neighbors:" + & " 'neighbor bts 2; neighbor lac 99 arfcn 123 bsic 45'"); + f_bts_0_cfg({"no neighbors", "neighbor bts 2", "neighbor lac 99 arfcn 123 bsic 45"}); + f_sleep(0.5); + + f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2", + "handover any to arfcn 871 bsic 12", + true); + f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO", + "handover any to arfcn 123 bsic 45", + true, true); +} + +testcase TC_ho_neighbor_config_1() runs on test_CT { + var MSC_ConnHdlr vc_conn; + f_init(3, true); + f_sleep(1.0); + vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1)); + vc_conn.done; +} +testcase TC_ho_neighbor_config_2() runs on test_CT { + var MSC_ConnHdlr vc_conn; + f_init(3, true); + f_sleep(1.0); + vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2)); + vc_conn.done; +} +testcase TC_ho_neighbor_config_3() runs on test_CT { + var MSC_ConnHdlr vc_conn; + f_init(3, true); + f_sleep(1.0); + vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3)); + vc_conn.done; +} +testcase TC_ho_neighbor_config_4() runs on test_CT { + var MSC_ConnHdlr vc_conn; + f_init(3, true); + f_sleep(1.0); + vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4)); + vc_conn.done; +} +testcase TC_ho_neighbor_config_5() runs on test_CT { + var MSC_ConnHdlr vc_conn; + f_init(3, true); + f_sleep(1.0); + vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5)); + vc_conn.done; +} +testcase TC_ho_neighbor_config_6() runs on test_CT { + var MSC_ConnHdlr vc_conn; + f_init(3, true); + f_sleep(1.0); + vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6)); + vc_conn.done; +} +testcase TC_ho_neighbor_config_7() runs on test_CT { + var MSC_ConnHdlr vc_conn; + f_init(3, true); + f_sleep(1.0); + vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7)); + vc_conn.done; +} + /* OS#3041: Open and close N connections in a normal fashion, and expect no * BSSMAP Reset just because of that. */ testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT { @@ -4140,6 +4496,14 @@ execute( TC_ho_in_fail_no_detect() ); execute( TC_ho_in_fail_no_detect2() ); + execute( TC_ho_neighbor_config_1() ); + execute( TC_ho_neighbor_config_2() ); + execute( TC_ho_neighbor_config_3() ); + execute( TC_ho_neighbor_config_4() ); + execute( TC_ho_neighbor_config_5() ); + execute( TC_ho_neighbor_config_6() ); + execute( TC_ho_neighbor_config_7() ); + execute( TC_bssap_rlsd_does_not_cause_bssmap_reset() ); execute( TC_bssmap_clear_does_not_cause_bssmap_reset() ); execute( TC_ms_rel_ind_does_not_cause_bssmap_reset() ); diff --git a/bsc/osmo-bsc.cfg b/bsc/osmo-bsc.cfg index bca5b20..9384491 100644 --- a/bsc/osmo-bsc.cfg +++ b/bsc/osmo-bsc.cfg @@ -57,7 +57,7 @@ encryption a5 0 1 3 neci 1 paging any use tch 0 - handover 0 + handover 1 handover window rxlev averaging 10 handover window rxqual averaging 1 handover window rxlev neighbor averaging 10 @@ -339,6 +339,35 @@ timeslot 7 phys_chan_config PDCH hopping enabled 0 + bts 3 + type sysmobts + band DCS1800 + cell_identity 3 + location_area_code 3 + # re-use bts 2's ARFCN 871 and BSIC 12 (to test handover config) + base_station_id_code 12 + trx 0 + rf_locked 0 + arfcn 871 + nominal power 23 + max_power_red 20 + rsl e1 tei 0 + timeslot 0 + phys_chan_config CCCH+SDCCH4 + timeslot 1 + phys_chan_config TCH/F + timeslot 2 + phys_chan_config TCH/F + timeslot 3 + phys_chan_config TCH/F + timeslot 4 + phys_chan_config TCH/F + timeslot 5 + phys_chan_config TCH/H + timeslot 6 + phys_chan_config PDCH + timeslot 7 + phys_chan_config PDCH msc 0 ip.access rtp-base 4000 no bsc-welcome-text diff --git a/library/RSL_Emulation.ttcn b/library/RSL_Emulation.ttcn index 790dd7a..309ec13 100644 --- a/library/RSL_Emulation.ttcn +++ b/library/RSL_Emulation.ttcn @@ -45,6 +45,8 @@ /* second BTS / DChan during hand-over */ port RSL_DCHAN_PT RSL1; port RSLEM_PROC_PT RSL1_PROC; + port RSL_DCHAN_PT RSL2; + port RSLEM_PROC_PT RSL2_PROC; }; type record RSLDC_ChanRqd { -- To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/14765 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-ttcn3-hacks Gerrit-Branch: master Gerrit-Change-Id: Ia4ba0e75abd3d45a3422b2525e5f938cdc5a04cc Gerrit-Change-Number: 14765 Gerrit-PatchSet: 3 Gerrit-Owner: neels <nhofm...@sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <lafo...@gnumonks.org> Gerrit-Reviewer: neels <nhofm...@sysmocom.de> Gerrit-Reviewer: pespin <pes...@sysmocom.de> Gerrit-MessageType: merged