blob: 55d302eecaf47c63b0ff6569b90f44c37f25a378 [file] [log] [blame]
/* OsmoS1GW (S1AP Gateway) test suite in TTCN-3
*
* (C) 2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Author: Vadim Yanitskiy <vyanitskiy@sysmocom.de>
*
* All rights reserved.
*
* Released under the terms of GNU General Public License, Version 2 or
* (at your option) any later version.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
module S1GW_Tests {
import from General_Types all;
import from Osmocom_Types all;
import from Native_Functions all;
import from IPL4asp_Types all;
import from Misc_Helpers all;
import from S1AP_CodecPort all;
import from S1AP_CodecPort_CtrlFunct all;
import from S1AP_Types all;
import from S1AP_Templates all;
import from S1AP_PDU_Descriptions all;
import from S1AP_IEs all;
import from S1AP_PDU_Contents all;
import from S1AP_Constants all;
import from S1AP_Server all;
modulepar {
charstring mp_s1gw_ip := "127.0.1.1";
charstring mp_mme_bind_ip := "127.0.2.10";
}
private type record of ConnHdlr ConnHdlrList;
type component ConnHdlr extends S1APSRV_ConnHdlr {
port S1AP_CODEC_PT S1AP_ENB;
var ConnectionId g_s1ap_conn_id := -1;
};
type component test_CT {
timer g_Tguard;
var S1AP_Server_CT vc_S1APSRV;
};
private altstep as_Tguard() runs on test_CT {
[] g_Tguard.timeout {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Tguard timeout");
}
}
template Global_ENB_ID
ts_Global_ENB_ID(integer enb_id := 0,
OCT3 plmn_id := '00f110'O) := {
pLMNidentity := plmn_id,
eNB_ID := {
macroENB_ID := int2bit(enb_id, 20)
},
iE_Extensions := omit
}
function f_init(float Tval := 20.0) runs on test_CT {
g_Tguard.start(Tval);
activate(as_Tguard());
}
function f_init_s1ap_srv() runs on test_CT {
var S1APSRV_ConnParams cpars := {
local_ip := mp_mme_bind_ip,
local_port := 36412
};
vc_S1APSRV := S1AP_Server_CT.create("S1APSRV-" & testcasename());
vc_S1APSRV.start(S1AP_Server.main(cpars));
}
type union ConnHdlrPars {
integer seed
};
type function void_fn(ConnHdlrPars pars) runs on ConnHdlr;
function f_ConnHdlr_spawn(void_fn fn, ConnHdlrPars pars)
runs on test_CT return ConnHdlr {
var ConnHdlr vc_conn;
vc_conn := ConnHdlr.create("ConnHdlr-" & testcasename());
connect(vc_conn:S1AP_CONN, vc_S1APSRV:S1AP_CLIENT);
connect(vc_conn:S1AP_PROC, vc_S1APSRV:S1AP_PROC);
vc_conn.start(derefers(fn)(pars));
return vc_conn;
}
function f_ConnHdlr_connect() runs on ConnHdlr {
var Result res;
map(self:S1AP_ENB, system:S1AP_CODEC_PT);
res := S1AP_CodecPort_CtrlFunct.f_IPL4_connect(S1AP_ENB,
mp_s1gw_ip, 36412,
"0.0.0.0", 0, -1,
{ sctp := valueof(ts_SCTP) });
if (not ispresent(res.connId)) {
setverdict(fail, "Could not create an S1AP socket, check your configuration");
mtc.stop;
}
g_s1ap_conn_id := res.connId;
log("eNB connection established");
}
function f_ConnHdlr_disconnect() runs on ConnHdlr {
var Result res;
S1AP_CodecPort_CtrlFunct.f_IPL4_close(S1AP_ENB, g_s1ap_conn_id,
{ sctp := valueof(ts_SCTP) });
g_s1ap_conn_id := -1;
unmap(self:S1AP_ENB, system:S1AP_CODEC_PT);
S1AP_CONN.receive(S1APSRV_Event:S1APSRV_EVENT_CONN_DOWN);
log("eNB connection closed");
}
function f_ConnHdlr_setup(Global_ENB_ID genb_id) runs on ConnHdlr {
var S1AP_PDU pdu;
timer T;
var SupportedTAs supported_tas_dummy := {
{
tAC := '0000'O,
broadcastPLMNs := { '00f000'O },
iE_Extensions := omit
}
};
S1AP_ENB.send(t_S1AP_Send(g_s1ap_conn_id,
ts_S1AP_SetupReq(genb_id,
supported_tas_dummy,
v32)));
T.start(1.0);
alt {
[] S1AP_CONN.receive(S1APSRV_Event:S1APSRV_EVENT_CONN_UP) { repeat; }
[] S1AP_CONN.receive(tr_S1AP_SetupReq) {
setverdict(pass);
T.stop;
}
[] S1AP_CONN.receive(S1AP_PDU:?) -> value pdu {
setverdict(fail, "Rx unexpected S1AP PDU: ", pdu);
T.stop;
}
[] T.timeout {
setverdict(fail, "Timeout waiting for S1AP SetupReq");
}
}
}
function f_TC_setup(ConnHdlrPars pars) runs on ConnHdlr {
var Global_ENB_ID genb_id := valueof(ts_Global_ENB_ID(pars.seed));
f_ConnHdlr_register(genb_id);
f_ConnHdlr_connect();
f_ConnHdlr_setup(genb_id);
f_sleep(0.5); /* keep the connection idle for some time */
f_ConnHdlr_disconnect();
f_ConnHdlr_unregister(genb_id);
}
testcase TC_setup() runs on test_CT {
var ConnHdlrPars pars := { seed := 0 };
var ConnHdlr vc_conn;
f_init();
f_init_s1ap_srv();
vc_conn := f_ConnHdlr_spawn(refers(f_TC_setup), pars);
vc_conn.done;
}
testcase TC_setup_multi() runs on test_CT {
var ConnHdlrList vc_conns := { };
f_init();
f_init_s1ap_srv();
for (var integer i := 0; i < 42; i := i + 1) {
var ConnHdlrPars pars := { seed := i };
var ConnHdlr vc_conn := f_ConnHdlr_spawn(refers(f_TC_setup), pars);
vc_conns := vc_conns & { vc_conn };
}
for (var integer i := 0; i < 42; i := i + 1) {
vc_conns[i].done;
}
}
control {
execute( TC_setup() );
execute( TC_setup_multi() );
}
}