fixeria has uploaded this change for review.
s1gw: add testcases for impatient eNB during MME pool selection
Two new test cases covering scenarios where the eNB disconnects before
S1 setup completes, targeting specific states of the enb_proxy FSM:
* TC_mme_pool_enb_disc_wait_s1setup_req: eNB connects but disconnects
before sending S1SetupReq (enb_proxy in wait_s1setup_req). No MME
connection is ever attempted; S1GW must handle the disconnect cleanly.
* TC_mme_pool_enb_disc_wait_s1setup_rsp: eNB sends S1SetupReq, S1GW
forwards it to the first pool MME (enb_proxy in wait_s1setup_rsp),
then eNB disconnects before the response arrives. S1GW must detect
the eNB disconnect and close the open MME connection in response.
A new helper S1GW_ConnHdlr.f_ConnHdlr_s1ap_close() is added for these
tests: unlike f_ConnHdlr_s1ap_disconnect(), it closes the eNB-side
socket without waiting for an S1APSRV_EVENT_CONN_DOWN from a pool
server (since in these scenarios either no MME connection exists
yet, or the CONN_DOWN is captured by the test body directly).
Change-Id: I5d27cdafcb9f595a2d3db59beff17cd55de2539e
Related: SYS#7052
---
M s1gw/S1GW_ConnHdlr.ttcn
M s1gw/S1GW_Tests.ttcn
M s1gw/expected-results.xml
3 files changed, 82 insertions(+), 1 deletion(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/59/42359/1
diff --git a/s1gw/S1GW_ConnHdlr.ttcn b/s1gw/S1GW_ConnHdlr.ttcn
index 2c900fe..574a2d0 100644
--- a/s1gw/S1GW_ConnHdlr.ttcn
+++ b/s1gw/S1GW_ConnHdlr.ttcn
@@ -179,6 +179,18 @@
log("eNB connection closed");
}
+/* Close the eNB-side SCTP connection without waiting for pool server events.
+ * For use in 'impatient eNB' scenarios where the eNB initiates teardown before
+ * S1 setup completes and no S1APSRV_EVENT_CONN_DOWN is expected in return. */
+function f_ConnHdlr_s1ap_close() runs on ConnHdlr {
+ f_ConnHdlr_conn_track_disable();
+ S1AP_CodecPort_CtrlFunct.f_IPL4_close(S1AP_ENB, g_s1ap_conn_id,
+ { sctp := c_SctpTuple_S1AP });
+ g_s1ap_conn_id := -1;
+ unmap(self:S1AP_ENB, system:S1AP_CODEC_PT);
+ log("eNB connection closed");
+}
+
function f_ConnHdlr_s1ap_expect_shutdown() runs on ConnHdlr {
S1AP_ENB.receive(tr_SctpShutDownEvent(g_s1ap_conn_id));
S1AP_ENB.receive(tr_SctpAssocChange(SCTP_SHUTDOWN_COMP, g_s1ap_conn_id));
diff --git a/s1gw/S1GW_Tests.ttcn b/s1gw/S1GW_Tests.ttcn
index 5fffb09..d870be8 100644
--- a/s1gw/S1GW_Tests.ttcn
+++ b/s1gw/S1GW_Tests.ttcn
@@ -1135,6 +1135,71 @@
{ S1APSRV_SETUP_REJECT, S1APSRV_SETUP_REJECT, S1APSRV_SETUP_REJECT });
}
+/* MME pool test: eNB connects but disconnects before sending S1SetupReq
+ * (S1GW is in wait_s1setup_req); S1GW must handle the disconnect cleanly
+ * and must not attempt to connect to any MME. */
+function f_TC_mme_pool_enb_disc_wait_s1setup_req(charstring id) runs on ConnHdlr {
+ f_ConnHdlr_s1ap_connect(mp_enb_bind_ip, mp_s1gw_enb_ip);
+
+ /* disconnect before S1SetupReq: S1GW is in wait_s1setup_req,
+ * no MME connection is ever attempted */
+ f_ConnHdlr_s1ap_close();
+ setverdict(pass);
+}
+testcase TC_mme_pool_enb_disc_wait_s1setup_req() runs on test_CT {
+ f_TC_exec_pool(refers(f_TC_mme_pool_enb_disc_wait_s1setup_req), 1,
+ { S1APSRV_SETUP_ACCEPT });
+}
+
+/* MME pool test: eNB connects, sends S1SetupReq, S1GW forwards it to an MME
+ * (S1GW is in wait_s1setup_rsp), then eNB disconnects before the response arrives.
+ * S1GW must detect the eNB disconnect and close the MME connection. */
+function f_TC_mme_pool_enb_disc_wait_s1setup_rsp(charstring id) runs on ConnHdlr {
+ var S1AP_Server_CT vc_srv := g_pars.pool_srvs[0];
+ var S1AP_PDU pdu;
+ timer T;
+
+ f_ConnHdlr_s1ap_connect(mp_enb_bind_ip, mp_s1gw_enb_ip);
+ f_ConnHdlr_conn_track_disable();
+
+ /* pre-register with the pool server, then trigger MME selection */
+ f_ConnHdlr_s1ap_register_to(g_pars.genb_id, vc_srv);
+ f_ConnHdlr_tx_s1ap_from_enb(ts_S1AP_SetupReq(g_pars.genb_id, c_SupportedTAs, v32));
+
+ /* wait until S1GW has forwarded SetupReq to the MME (now in wait_s1setup_rsp) */
+ g_s1ap_server := vc_srv;
+ T.start(10.0);
+ alt {
+ [] S1AP_CONN.receive(S1APSRV_Event:S1APSRV_EVENT_CONN_UP) from vc_srv { repeat; }
+ [] S1AP_CONN.receive(tr_S1AP_SetupReq) from vc_srv -> value pdu { T.stop; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for S1SetupReq on pool server");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ /* eNB disconnects impatient; S1GW must close the MME connection in response */
+ f_ConnHdlr_s1ap_close();
+
+ T.start(10.0);
+ alt {
+ [] S1AP_CONN.receive(S1APSRV_Event:S1APSRV_EVENT_CONN_DOWN) from vc_srv {
+ T.stop;
+ setverdict(pass);
+ }
+ [] T.timeout {
+ setverdict(fail, "S1GW did not close MME connection after eNB disconnect");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ f_ConnHdlr_s1ap_unregister_from(g_pars.genb_id, vc_srv);
+}
+testcase TC_mme_pool_enb_disc_wait_s1setup_rsp() runs on test_CT {
+ f_TC_exec_pool(refers(f_TC_mme_pool_enb_disc_wait_s1setup_rsp), 1,
+ { S1APSRV_SETUP_ACCEPT });
+}
+
control {
execute( TC_setup() );
execute( TC_setup_multi() );
@@ -1174,6 +1239,8 @@
execute( TC_mme_pool_reject_fallback() );
execute( TC_mme_pool_timeout_fallback() );
execute( TC_mme_pool_all_reject() );
+ execute( TC_mme_pool_enb_disc_wait_s1setup_req() );
+ execute( TC_mme_pool_enb_disc_wait_s1setup_rsp() );
}
}
diff --git a/s1gw/expected-results.xml b/s1gw/expected-results.xml
index 28fcf71..0769764 100644
--- a/s1gw/expected-results.xml
+++ b/s1gw/expected-results.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<testsuite name='S1GW_Tests' tests='36' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
+<testsuite name='S1GW_Tests' tests='38' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
<testcase classname='S1GW_Tests' name='TC_setup' time='MASKED'/>
<testcase classname='S1GW_Tests' name='TC_setup_multi' time='MASKED'/>
<testcase classname='S1GW_Tests' name='TC_conn_term_by_mme' time='MASKED'/>
@@ -38,4 +38,6 @@
<testcase classname='S1GW_Tests' name='TC_mme_pool_reject_fallback' time='MASKED'/>
<testcase classname='S1GW_Tests' name='TC_mme_pool_timeout_fallback' time='MASKED'/>
<testcase classname='S1GW_Tests' name='TC_mme_pool_all_reject' time='MASKED'/>
+ <testcase classname='S1GW_Tests' name='TC_mme_pool_enb_disc_wait_s1setup_req' time='MASKED'/>
+ <testcase classname='S1GW_Tests' name='TC_mme_pool_enb_disc_wait_s1setup_rsp' time='MASKED'/>
</testsuite>
To view, visit change 42359. To unsubscribe, or for help writing mail filters, visit settings.