neels has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/37077?usp=email )
(
3 is the latest approved patch-set. No files were changed between the latest approved patch-set and the submitted one. )Change subject: hnbgw: TC_hnb_disconnected_timeout ......................................................................
hnbgw: TC_hnb_disconnected_timeout
Test the new timer hnbgw X35: discard all hnb_persistent state after a given timeout.
While a hnb_persistent is present, its rate_ctrs and stat_items remain present. When it is discarded, these vanish again. Use this to verify that discarding and re-registering a hnb_persistent works.
Set X35 to five seconds, drop the Iuh link, wait and verify that the rate counter group for the hnb_persistent is gone.
Then reconnect and disconnect again, to provoke errors like use-after-free.
Depends: osmo-hnbgw Ic819d7cbc03fb39e98c204b70d016c5170dc6307 Related: SYS#6773 Change-Id: Ibec009203d38f65714561b7c28edbdbd8b34e704 --- M hnbgw/HNBGW_Tests.ttcn M library/Osmocom_CTRL_Functions.ttcn 2 files changed, 167 insertions(+), 0 deletions(-)
Approvals: pespin: Looks good to me, but someone else must approve Jenkins Builder: Verified laforge: Looks good to me, but someone else must approve neels: Looks good to me, approved
diff --git a/hnbgw/HNBGW_Tests.ttcn b/hnbgw/HNBGW_Tests.ttcn index 88b8c1e..273627d 100644 --- a/hnbgw/HNBGW_Tests.ttcn +++ b/hnbgw/HNBGW_Tests.ttcn @@ -357,6 +357,7 @@ var charstring g_ctr_cn_node_name; /* Counter state */ var CounterNameValsList g_ctr_cn; + var CounterNameValsList g_ctr_hnb; }
/* global altstep for global guard timer; */ @@ -433,6 +434,15 @@ vc_RUA[hnb_idx].start(RUA_Emulation.main(rua_ops, id & "-RUA")); }
+function f_drop_hnodeb(integer hnb_idx) runs on test_CT +{ + + vc_Iuh[hnb_idx].stop; + vc_RUA[hnb_idx].stop; + disconnect(self:HNBAP[hnb_idx], vc_Iuh[hnb_idx]:HNBAP); + disconnect(vc_RUA[hnb_idx]:RUA, vc_Iuh[hnb_idx]:RUA); +} + private type record of boolean BooleanList;
private function f_vty_cnlink_allow_attach(TELNETasp_PT pt, boolean ps_domain, BooleanList allow_attach_list) @@ -1016,6 +1026,114 @@ f_shutdown_helper(); }
+/* Default list of counters for a 'hnb' entity */ +const CounterNameVals counternames_hnb := { + { "iuh:established", 0 } +}; + +private function f_ctrs_hnb_init(integer hnb_start := 0, integer hnb_count := 1, + CounterNameVals counternames := counternames_hnb) runs on test_CT { + g_ctr_hnb := f_counter_name_vals_get_n(IPA_CTRL, "hnb", hnb_count, counternames, start_idx := hnb_start); + log("initial hnb rate counters: ", g_ctr_hnb); +} + +/* f_ctrs_hnb_init(); + * f_do_thing(on_hnb := 0); + * f_do_thing(on_hnb := 0); + * f_do_other(on_hnb := 1); + * f_ctrs_hnb_add(0, "thing", 2); + * f_ctrs_hnb_add(1, "other"); + * f_ctrs_hnb_verify(); + */ +private function f_ctrs_hnb_verify() runs on test_CT { + log("verifying hnb rate counters: ", g_ctr_hnb); + f_counter_name_vals_expect_n(IPA_CTRL, "hnb", g_ctr_hnb); +} + +/* convenience: f_ctrs_hnb_add() and f_ctrs_hnb_verify() in one call. + * f_ctrs_hnb_init(); + * f_do_thing(on_hnb := 0); + * f_do_thing(on_hnb := 0); + * f_do_thing(on_hnb := 0); + * f_ctrs_hnb_expect(0, "thing", 3); + */ +private function f_ctrs_hnb_expect(integer hnb_nr, charstring countername, integer val := 1) runs on test_CT { + f_ctrs_hnb_add(hnb_nr, countername, val); + f_ctrs_hnb_verify(); +} + +private function f_ctrs_hnb_add(integer hnb_nr, charstring countername, integer val := 1) runs on test_CT { + f_counter_name_vals_list_add(g_ctr_hnb, hnb_nr, countername, val); +} + +/* Set all counters for this hnb instance to a specific value. Useful to expect a disconnected and discarded hnb, + * because -1 is returned by f_counter_name_vals_get_n() when the hnb is not present on the CTRL interface. */ +private function f_ctrs_hnb_set_all(integer hnb_nr, integer val) runs on test_CT { + for (var integer i := 0; i < lengthof(counternames_hnb); i := i + 1) { + f_counter_name_vals_list_set(g_ctr_hnb, hnb_nr, counternames_hnb[i].name, val); + } +} + +private function f_vty_run_hnbgw(TELNETasp_PT pt, charstring cmd) +{ + f_vty_enter_config(pt); + f_vty_transceive(pt, "hnbgw"); + f_vty_transceive(pt, cmd); + f_vty_transceive(pt, "end"); +} + +testcase TC_hnb_disconnected_timeout() runs on test_CT { + g_num_hnbs := 1; + f_init(start_hnb := true); + + f_vty_run_hnbgw(HNBGWVTY, "timer hnbgw X35 5"); + + /* Init the counters when the hnb already exists. There should be a nonzero iuh:established count now. */ + f_ctrs_hnb_init(); + + /* Drop the Iuh link */ + f_drop_hnodeb(0); + f_sleep(1.0); + + /* The hNodeB persistent state should still be around, because X35 has not yet elapsed. */ + f_ctrs_hnb_verify(); + + f_sleep(5.0); + /* We get -1 counters when the CTRL interface returned an error for the requested counter, meaning that the + * hnb_persistent no longer exists. Verify that it is gone: */ + f_ctrs_hnb_set_all(0, -1); + f_ctrs_hnb_verify(); + + f_sleep(1.0); + + /* Connect again. */ + var RuaOps rua_ops := { + create_cb := refers(IuhRanapCreateCallback), + unitdata_cb := refers(IuhRanapUnitdataCallback) + }; + f_init_hnodeb(testcasename(), 0, rua_ops); + + /* still disconnected until actually registered on HNBAP */ + f_ctrs_hnb_verify(); + + f_hnbap_hnb_register(0); + /* The hNodeB has come back to existence, so expect 0, not -1 anymore: */ + f_ctrs_hnb_set_all(0, 0); + /* Also we've registered once. */ + f_ctrs_hnb_add(0, "iuh:established", 1); + f_ctrs_hnb_verify(); + f_sleep(1.0); + + /* Again drop the Iuh link, wait for X35 and see that it's gone again. */ + f_drop_hnodeb(0); + f_ctrs_hnb_verify(); + f_sleep(6.0); + f_ctrs_hnb_set_all(0, -1); + f_ctrs_hnb_verify(); + + f_shutdown_helper(); +} + /* regular UE registration */ testcase TC_ue_register() runs on test_CT { var UE_Identity ue_id := { iMSI := imsi_hex2oct(f_gen_imsi(1)) }; @@ -2882,6 +3000,7 @@ execute(TC_hnb_register()); execute(TC_hnb_register_duplicate()); execute(TC_hnb_register_duplicate_reuse_sctp_assoc()); + execute(TC_hnb_disconnected_timeout()); execute(TC_ue_register()); execute(TC_ue_register_tmsi_lai()); execute(TC_ue_register_before_hnb_register()); diff --git a/library/Osmocom_CTRL_Functions.ttcn b/library/Osmocom_CTRL_Functions.ttcn index 5202418..f8788b9 100644 --- a/library/Osmocom_CTRL_Functions.ttcn +++ b/library/Osmocom_CTRL_Functions.ttcn @@ -264,6 +264,22 @@ } }
+ /* In a list of one instance's counters, set a specifically named counter to a specific value. */ + function f_counter_name_vals_set(inout CounterNameVals vals, charstring countername, integer val := 1) + { + for (var integer i := 0; i < lengthof(vals); i := i + 1) { + if (vals[i].name == countername) { + vals[i].val := val; + return; + } + } + /* name not found, append */ + vals[lengthof(vals)] := { + name := countername, + val := val + } + } + /* In a list of several instances' counters, increment a specific instance's specifically named counter. */ function f_counter_name_vals_list_add(inout CounterNameValsList vals, integer instance_nr, charstring countername, integer val := 1) @@ -271,6 +287,14 @@ f_counter_name_vals_add(vals[instance_nr], countername, val); }
+ /* In a list of several instances' counters, set a specific instance's specifically named counter to a specific + * value. */ + function f_counter_name_vals_list_set(inout CounterNameValsList vals, integer instance_nr, + charstring countername, integer val := 0) + { + f_counter_name_vals_set(vals[instance_nr], countername, val); + } + /* For a specific instance, call f_counter_name_vals_get() and compare with expected counter values. * Set the test verdict accordingly. */ function f_counter_name_vals_expect(IPA_CTRL_PT pt, charstring instance_name, integer instance_nr,