neels has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/35098?usp=email )
Change subject: bsc: tests recovery from BORKEN after release failed ...................................................................... bsc: tests recovery from BORKEN after release failed Related: osmo-bsc Ic4728b3efe843ea63e2a0b54b1ea8a925347484a Related: SYS#6655 Change-Id: I9b4ddfc4a337808d9d5ec538c25fd390b1b2530f --- M bsc/BSC_Tests.ttcn 1 file changed, 139 insertions(+), 3 deletions(-) Approvals: daniel: Looks good to me, but someone else must approve laforge: Looks good to me, approved Jenkins Builder: Verified diff --git a/bsc/BSC_Tests.ttcn b/bsc/BSC_Tests.ttcn index 57b44e0..1fc42ba 100644 --- a/bsc/BSC_Tests.ttcn +++ b/bsc/BSC_Tests.ttcn @@ -8529,7 +8529,8 @@ } friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC, - template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE) + template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE, + boolean send_rel_ack := true) runs on MSC_ConnHdlr { var default ack_dlcx := activate(as_mgcp_ack_all_dlcx()); var default ack_rel_req := activate(as_rsl_ack_all_rel_req()); @@ -8549,8 +8550,10 @@ } [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) { f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack"); - rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr)); - f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt); + if (send_rel_ack) { + rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr)); + f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt); + } } } deactivate(ack_dlcx); @@ -12439,6 +12442,125 @@ f_shutdown_helper(ho := true); } +private function f_vty_expect_borken(TELNETasp_PT pt, boolean expect_borken) +{ + var charstring lchan_summary; + lchan_summary := f_vty_transceive_ret(pt, "show lchan summary"); + var boolean found_borken := (f_strstr(lchan_summary, "State BORKEN") >= 0); + if (found_borken != expect_borken) { + if (expect_borken) { + setverdict(fail, "Expected 'BORKEN' state in ", lchan_summary); + } else { + setverdict(fail, "Expected no 'BORKEN' state in ", lchan_summary); + } + mtc.stop; + } +} + +private function f_tc_unbreak_lchan_after_missing_rel_ack(integer test_variant) runs on MSC_ConnHdlr { + + /* Establish a channel, so we can mess with the release of it. */ + var template PDU_BSSAP exp_compl := f_gen_exp_compl(); + var PDU_BSSAP ass_cmd := f_gen_ass_req(); + + ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType); + ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR})); + + f_establish_fully(ass_cmd, exp_compl); + + /* shorten X28, the time after which a BORKEN lchan recovers, from 30s to something short */ + f_vty_enter_cfg_network(BSCVTY); + f_vty_transceive(BSCVTY, "timer X28 3"); + f_vty_transceive(BSCVTY, "end"); + + /* Allow us to include handling of Channel Activation in this component, to test recovery from BORKEN */ + f_rslem_set_auto_chan_act_ack(RSL_PROC, false); + + /* give a moment before releasing */ + f_sleep(2.0); + + /* Perform a channel release, but omit the RF CHAN REL ACK. The aim is to get the lchan to go BORKEN. */ + f_perform_clear(send_rel_ack := false); + + f_vty_expect_borken(BSCVTY, false); + + /* After a timeout of X6, the lchan ends up in LCHAN_ST_BORKEN */ + f_sleep(6.0); + + f_vty_expect_borken(BSCVTY, true); + + /* Now within two seconds, we expect OsmoBSC to attempt recovering from the broken state. + * + * test_variant == 1: + * It will first attempt a Channel Activation. If the BTS accepts that, it means the state is back in sync. + * Then OsmoBSC releases the lchan again and makes it available for use. + * + * test_variant == 2: + * It will first attempt a Channel Activation and the BTS NACKs that. + * It will then attempt a release, which we ACK, and the channel will be available again. + */ + + /* Receive the Channel Activation */ + var ASP_RSL_Unitdata rx_rsl_ud; + RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud; + + var RslChannelNr chan_nr; + var RSL_IE_Body ie; + if (f_rsl_find_ie(rx_rsl_ud.rsl, RSL_IE_CHAN_NR, ie) == true) { + chan_nr := ie.chan_nr; + } else { + setverdict(fail, "Unable to find RSL_IE_CHAN_NR in ", rx_rsl_ud); + return; + } + + if (test_variant == 1) { + RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId)); + + /* Back in sync, receive the Channel Release */ + RSL.receive(tr_RSL_RF_CHAN_REL(chan_nr)); + RSL.send(ts_RSL_RF_CHAN_REL_ACK(chan_nr)); + } else if (test_variant == 2) { + RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL), rx_rsl_ud.streamId)); + + /* Instead tries a release */ + RSL.receive(tr_RSL_RF_CHAN_REL(chan_nr)); + RSL.send(ts_RSL_RF_CHAN_REL_ACK(chan_nr)); + /* That worked, channel usable again */ + } else { + setverdict(fail, "undefined test_variant ", test_variant); + } + + f_vty_expect_borken(BSCVTY, false); + setverdict(pass); +} + +/* Test recovery path from a BORKEN lchan */ +private function f_TC_unbreak_lchan_after_missing_rel_ack_1(charstring id) runs on MSC_ConnHdlr { + f_tc_unbreak_lchan_after_missing_rel_ack(test_variant := 1); +} +testcase TC_unbreak_lchan_after_missing_rel_ack_1() runs on test_CT { + var TestHdlrParams pars := f_gen_test_hdlr_pars(); + var MSC_ConnHdlr vc_conn; + f_init(1, true); + f_sleep(1.0); + vc_conn := f_start_handler(refers(f_TC_unbreak_lchan_after_missing_rel_ack_1), pars); + vc_conn.done; + f_shutdown_helper(); +} + +private function f_TC_unbreak_lchan_after_missing_rel_ack_2(charstring id) runs on MSC_ConnHdlr { + f_tc_unbreak_lchan_after_missing_rel_ack(test_variant := 2); +} +testcase TC_unbreak_lchan_after_missing_rel_ack_2() runs on test_CT { + var TestHdlrParams pars := f_gen_test_hdlr_pars(); + var MSC_ConnHdlr vc_conn; + f_init(1, true); + f_sleep(1.0); + vc_conn := f_start_handler(refers(f_TC_unbreak_lchan_after_missing_rel_ack_2), pars); + vc_conn.done; + f_shutdown_helper(); +} + control { /* CTRL interface testing */ execute( TC_ctrl_msc_connection_status() ); @@ -12792,6 +12914,9 @@ /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */ execute( TC_ho_out_of_this_bsc() ); + + execute( TC_unbreak_lchan_after_missing_rel_ack_1() ); + execute( TC_unbreak_lchan_after_missing_rel_ack_2() ); } } -- To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/35098?usp=email 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: I9b4ddfc4a337808d9d5ec538c25fd390b1b2530f Gerrit-Change-Number: 35098 Gerrit-PatchSet: 2 Gerrit-Owner: neels <nhofm...@sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: daniel <dwillm...@sysmocom.de> Gerrit-Reviewer: laforge <lafo...@osmocom.org> Gerrit-Reviewer: neels <nhofm...@sysmocom.de> Gerrit-MessageType: merged