mme: initial skeleton for MME / SGsAP tetss
Change-Id: Idbd54838daaf12acccc3253dc4278de75eaaaf31
This commit is contained in:
parent
97ae972c4a
commit
b8a4ac80a6
|
@ -47,6 +47,12 @@ type port SGsAP_Conn_PT message {
|
|||
inout PDU_SGsAP, PDU_ML3_MS_NW, PDU_ML3_NW_MS;
|
||||
} with { extension "internal" };
|
||||
|
||||
/* global test port e.g. for non-imsi/conn specific messages */
|
||||
type port SGsAP_PT message {
|
||||
inout PDU_SGsAP;
|
||||
} with { extension "internal" };
|
||||
|
||||
|
||||
/* represents a single SGsAP Association */
|
||||
type record AssociationData {
|
||||
SGsAP_ConnHdlr comp_ref,
|
||||
|
@ -66,6 +72,8 @@ type component SGsAP_Emulation_CT {
|
|||
var ExpectData SgsapExpectTable[8];
|
||||
/* procedure based port to register for incoming connections */
|
||||
port SGsAPEM_PROC_PT SGsAP_PROC;
|
||||
/* test port for unit data messages */
|
||||
port SGsAP_PT SGsAP_UNIT;
|
||||
|
||||
var charstring g_sgsap_id;
|
||||
var integer g_sgsap_conn_id := -1;
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/* MME (Mobility Management Engine) test suite in TTCN-3
|
||||
* (C) 2019 Harald Welte <laforge@gnumonks.org>
|
||||
* 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 MME_Tests {
|
||||
|
||||
import from SGsAP_Types all;
|
||||
import from SGsAP_Templates all;
|
||||
import from SGsAP_Emulation all;
|
||||
|
||||
import from L3_Templates all;
|
||||
import from DNS_Helpers all;
|
||||
|
||||
friend module MME_Tests_SGsAP;
|
||||
|
||||
type component MTC_CT {
|
||||
var SGsAP_Emulation_CT vc_SGsAP;
|
||||
port SGsAP_PT SGsAP_UNIT;
|
||||
port SGsAPEM_PROC_PT SGsAP_PROC;
|
||||
}
|
||||
|
||||
type component ConnHdlr extends SGsAP_ConnHdlr {
|
||||
var ConnHdlrPars g_pars;
|
||||
timer g_Tguard := 30.0;
|
||||
}
|
||||
|
||||
type record ConnHdlrPars {
|
||||
hexstring imsi
|
||||
}
|
||||
|
||||
modulepar {
|
||||
charstring mp_sgs_local_ip := "127.0.0.1";
|
||||
integer mp_sgs_local_port := 29118;
|
||||
charstring mp_vlr_name := "vlr.example.net";
|
||||
charstring mp_mme_name := "mmec01.mmegi0001.mme.epc.mnc070.mcc901.3gppnetwork.org";
|
||||
}
|
||||
|
||||
/* send incoming unit data messages (like reset) to global SGsAP_UNIT port */
|
||||
friend function ForwardUnitdataCallback(PDU_SGsAP msg)
|
||||
runs on SGsAP_Emulation_CT return template PDU_SGsAP {
|
||||
SGsAP_UNIT.send(msg);
|
||||
return omit;
|
||||
}
|
||||
|
||||
friend function f_init_sgsap(charstring id) runs on MTC_CT {
|
||||
id := id & "-SGsAP";
|
||||
var SGsAPOps ops := {
|
||||
create_cb := refers(SGsAP_Emulation.ExpectedCreateCallback),
|
||||
unitdata_cb := refers(ForwardUnitdataCallback)
|
||||
}
|
||||
var SGsAP_conn_parameters pars := {
|
||||
remote_ip := "",
|
||||
remote_sctp_port := -1,
|
||||
local_ip := mp_sgs_local_ip,
|
||||
local_sctp_port := mp_sgs_local_port
|
||||
}
|
||||
|
||||
vc_SGsAP := SGsAP_Emulation_CT.create(id);
|
||||
map(vc_SGsAP:SGsAP, system:SGsAP_CODEC_PT);
|
||||
connect(vc_SGsAP:SGsAP_PROC, self:SGsAP_PROC);
|
||||
connect(vc_SGsAP:SGsAP_UNIT, self:SGsAP_UNIT);
|
||||
vc_SGsAP.start(SGsAP_Emulation.main(ops, pars, id));
|
||||
}
|
||||
|
||||
/* generate parameters for a connection handler */
|
||||
friend function f_init_pars(integer imsi_suffix)
|
||||
runs on MTC_CT return ConnHdlrPars {
|
||||
var ConnHdlrPars pars := {
|
||||
imsi := f_gen_imsi(imsi_suffix)
|
||||
};
|
||||
return pars;
|
||||
}
|
||||
|
||||
type function void_fn(ConnHdlrPars pars) runs on ConnHdlr;
|
||||
|
||||
/* start a connection handler with given parameters */
|
||||
friend function f_start_handler_with_pars(void_fn fn, ConnHdlrPars pars, integer s1ap_idx := 0)
|
||||
runs on MTC_CT return ConnHdlr {
|
||||
var ConnHdlr vc_conn;
|
||||
var charstring id := testcasename() & int2str(s1ap_idx);
|
||||
|
||||
vc_conn := ConnHdlr.create(id);
|
||||
/* SGsAP part */
|
||||
connect(vc_conn:SGsAP, vc_SGsAP:SGsAP_CLIENT);
|
||||
connect(vc_conn:SGsAP_PROC, vc_SGsAP:SGsAP_PROC);
|
||||
|
||||
/* We cannot use vc_conn.start(f_init_handler(fn, id, pars)); as we cannot have
|
||||
* a stand-alone 'derefers()' call, see https://www.eclipse.org/forums/index.php/t/1091364/ */
|
||||
vc_conn.start(derefers(fn)(pars));
|
||||
return vc_conn;
|
||||
}
|
||||
|
||||
/* altstep for the global guard timer */
|
||||
private altstep as_Tguard()runs on ConnHdlr {
|
||||
[] g_Tguard.timeout {
|
||||
setverdict(fail, "Tguard timeout");
|
||||
mtc.stop;
|
||||
}
|
||||
}
|
||||
|
||||
friend function f_init_handler(ConnHdlrPars pars, float t_guard := 30.0) runs on ConnHdlr {
|
||||
/* make parameters available via component variable */
|
||||
g_pars := pars;
|
||||
/* start guard timre and activate it as default */
|
||||
g_Tguard.start(t_guard);
|
||||
activate(as_Tguard());
|
||||
/* Route all SGsAP mesages for our IMSIto us */
|
||||
f_create_sgsap_expect(pars.imsi);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,210 @@
|
|||
module MME_Tests_SGsAP {
|
||||
|
||||
/* Osmocom MME test suite in in TTCN-3
|
||||
* (C) 2019 Harald Welte <laforge@gnumonks.org>
|
||||
* 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
|
||||
*/
|
||||
|
||||
import from SGsAP_Types all;
|
||||
import from SGsAP_Templates all;
|
||||
import from SGsAP_Emulation all;
|
||||
|
||||
import from General_Types all;
|
||||
import from Osmocom_Types all;
|
||||
import from L3_Templates all;
|
||||
import from DNS_Helpers all;
|
||||
import from MME_Tests all;
|
||||
|
||||
/* performa SGs reset procedure */
|
||||
function f_sgsap_vlr_reset() runs on ConnHdlr {
|
||||
var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
|
||||
var octetstring mme_name := f_enc_dns_hostname(mp_mme_name);
|
||||
|
||||
SGsAP.send(ts_SGsAP_RESET_IND_VLR(vlr_name));
|
||||
alt {
|
||||
[] SGsAP.receive(tr_SGsAP_RESET_ACK(mme_name, vlr_name)) {
|
||||
setverdict(pass);
|
||||
}
|
||||
[] SGsAP.receive(tr_SGsAP_RESET_ACK(?, ?)) {
|
||||
setverdict(fail, "Received unexpected VLR/MME name in SGsAP RESET ACK");
|
||||
}
|
||||
[] SGsAP.receive {
|
||||
setverdict(fail, "Received unexpected response to SGsAP RESET");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* perform a SGs paging procedure */
|
||||
function f_sgsap_page(Service_Indicator serv_ind, template (omit) OCT4 tmsi,
|
||||
template (omit) SGs_Cause exp_cause) runs on ConnHdlr {
|
||||
var octetstring vlr_name := f_enc_dns_hostname(mp_vlr_name);
|
||||
var boolean exp_success := true;
|
||||
var PDU_SGsAP rx;
|
||||
if (not istemplatekind(exp_cause, "omit")) {
|
||||
exp_success := false;
|
||||
}
|
||||
SGsAP.send(ts_SGsAP_PAGING_REQ(g_pars.imsi, vlr_name, serv_ind, tmsi));
|
||||
alt {
|
||||
/* we expect success */
|
||||
[exp_success] SGsAP.receive(tr_SGsAP_SERVICE_REQ(g_pars.imsi, serv_ind, ?)) {
|
||||
setverdict(pass);
|
||||
}
|
||||
[exp_success] SGsAP.receive(tr_SGsAP_PAGING_REJ(g_pars.imsi, ?)) {
|
||||
setverdict(fail, "Received unexpected PAGING REJECT");
|
||||
}
|
||||
/* we expect failure */
|
||||
[not exp_success] SGsAP.receive(tr_SGsAP_SERVICE_REQ(g_pars.imsi, serv_ind, ?)) {
|
||||
setverdict(fail, "Received SERVICE REQ waiting for PAGING REJECT");
|
||||
}
|
||||
[not exp_success] SGsAP.receive(tr_SGsAP_PAGING_REJ(g_pars.imsi, exp_cause)) {
|
||||
setverdict(pass);
|
||||
}
|
||||
[not exp_success] SGsAP.receive(tr_SGsAP_PAGING_REJ(g_pars.imsi, ?)) {
|
||||
setverdict(fail, "Received unexpected PAGING REJECT cause");
|
||||
}
|
||||
[] SGsAP.receive {
|
||||
setverdict(fail, "Received unexpected SgSAP");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* perform a SGs alert procedure */
|
||||
function f_sgsap_alert(template (omit) SGs_Cause exp_cause) runs on ConnHdlr{
|
||||
var boolean exp_success := true;
|
||||
var PDU_SGsAP rx;
|
||||
if (not istemplatekind(exp_cause, "omit")) {
|
||||
exp_success := false;
|
||||
}
|
||||
SGsAP.send(ts_SGsAP_ALERT_REQ(g_pars.imsi));
|
||||
alt {
|
||||
[exp_success] SGsAP.receive(tr_SGsAP_ALERT_ACK(g_pars.imsi)) {
|
||||
setverdict(pass);
|
||||
}
|
||||
[exp_success] SGsAP.receive(tr_SGsAP_ALERT_REJECT(g_pars.imsi, ?)) -> value rx {
|
||||
setverdict(fail, "Received unexpected ALERT REJECT ", rx);
|
||||
}
|
||||
[not exp_success] SGsAP.receive(tr_SGsAP_ALERT_ACK(g_pars.imsi)) {
|
||||
setverdict(fail, "Received unexpected ALERT ACK");
|
||||
}
|
||||
[not exp_success] SGsAP.receive(tr_SGsAP_ALERT_REJECT(g_pars.imsi, exp_cause)) {
|
||||
setverdict(pass)
|
||||
}
|
||||
[not exp_success] SGsAP.receive(tr_SGsAP_ALERT_REJECT(g_pars.imsi, ?)) -> value rx {
|
||||
setverdict(fail, "Received ALERT REJECT with unexpected cause ", rx);
|
||||
}
|
||||
[] SGsAP.receive {
|
||||
setverdict(fail, "Received unexpected SGsAP");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Test if MME responds to VLR-originated RESET procedure as expected */
|
||||
private function f_TC_sgsap_vlr_reset(ConnHdlrPars pars) runs on ConnHdlr {
|
||||
f_init_handler(pars);
|
||||
f_sgsap_vlr_reset();
|
||||
}
|
||||
testcase TC_sgsap_vlr_reset() runs on MTC_CT {
|
||||
var ConnHdlrPars pars;
|
||||
var ConnHdlr vc_conn;
|
||||
f_init_sgsap(testcasename());
|
||||
pars := f_init_pars(1);
|
||||
vc_conn := f_start_handler_with_pars(refers(f_TC_sgsap_vlr_reset), pars);
|
||||
vc_conn.done;
|
||||
}
|
||||
|
||||
/* Page known subscriber for SMS */
|
||||
private function f_TC_sgsap_paging_sms(ConnHdlrPars pars) runs on ConnHdlr {
|
||||
f_init_handler(pars);
|
||||
/* TODO: register subscriber on S1 */
|
||||
f_sgsap_page(SMS_indicator, omit, omit);
|
||||
}
|
||||
testcase TC_sgsap_paging_sms() runs on MTC_CT {
|
||||
var ConnHdlrPars pars;
|
||||
var ConnHdlr vc_conn;
|
||||
f_init_sgsap(testcasename());
|
||||
pars := f_init_pars(2);
|
||||
vc_conn := f_start_handler_with_pars(refers(f_TC_sgsap_paging_sms), pars);
|
||||
vc_conn.done;
|
||||
}
|
||||
|
||||
/* Page known subscriber for CS call */
|
||||
private function f_TC_sgsap_paging_cs(ConnHdlrPars pars) runs on ConnHdlr {
|
||||
f_init_handler(pars);
|
||||
/* TODO: register subscriber on S1 */
|
||||
f_sgsap_page(CS_call_indicator, omit, omit);
|
||||
}
|
||||
testcase TC_sgsap_paging_cs() runs on MTC_CT {
|
||||
var ConnHdlrPars pars;
|
||||
var ConnHdlr vc_conn;
|
||||
f_init_sgsap(testcasename());
|
||||
pars := f_init_pars(3);
|
||||
vc_conn := f_start_handler_with_pars(refers(f_TC_sgsap_paging_cs), pars);
|
||||
vc_conn.done;
|
||||
}
|
||||
|
||||
|
||||
/* Page unknown subscriber; expect PAGING REJECT from MME */
|
||||
private function f_TC_sgsap_paging_reject(ConnHdlrPars pars) runs on ConnHdlr {
|
||||
f_init_handler(pars);
|
||||
f_sgsap_page(SMS_indicator, omit, IMSI_unknown);
|
||||
}
|
||||
testcase TC_sgsap_paging_reject() runs on MTC_CT {
|
||||
var ConnHdlrPars pars;
|
||||
var ConnHdlr vc_conn;
|
||||
f_init_sgsap(testcasename());
|
||||
pars := f_init_pars(4);
|
||||
vc_conn := f_start_handler_with_pars(refers(f_TC_sgsap_paging_reject), pars);
|
||||
vc_conn.done;
|
||||
}
|
||||
|
||||
/* Send ALERT-REQ to MME; perform S1AP activity; expect ALERT-ACK on SGs */
|
||||
private function f_TC_sgsap_alert(ConnHdlrPars pars) runs on ConnHdlr {
|
||||
f_init_handler(pars);
|
||||
/* TODO: register subscriber on S1 */
|
||||
f_sgsap_alert(omit);
|
||||
/* TOOD: do something on S1 triggering UE ACT IND */
|
||||
SGsAP.receive(tr_SGsAP_UE_ACT_IND(g_pars.imsi));
|
||||
}
|
||||
testcase TC_sgsap_alert() runs on MTC_CT {
|
||||
var ConnHdlrPars pars;
|
||||
var ConnHdlr vc_conn;
|
||||
f_init_sgsap(testcasename());
|
||||
pars := f_init_pars(5);
|
||||
vc_conn := f_start_handler_with_pars(refers(f_TC_sgsap_alert), pars);
|
||||
vc_conn.done;
|
||||
}
|
||||
|
||||
/* Send ALERT-REQ to MME for unidentified IMSI; expect ALERT-REJ on SGs */
|
||||
private function f_TC_sgsap_alert_rej(ConnHdlrPars pars) runs on ConnHdlr {
|
||||
f_init_handler(pars);
|
||||
/* IMSI doesn't register and is hence unknown */
|
||||
f_sgsap_alert(IMSI_unknown);
|
||||
}
|
||||
testcase TC_sgsap_alert_rej() runs on MTC_CT {
|
||||
var ConnHdlrPars pars;
|
||||
var ConnHdlr vc_conn;
|
||||
f_init_sgsap(testcasename());
|
||||
pars := f_init_pars(6);
|
||||
vc_conn := f_start_handler_with_pars(refers(f_TC_sgsap_alert_rej), pars);
|
||||
vc_conn.done;
|
||||
}
|
||||
|
||||
|
||||
/* Test SGsAP-DOWNLINK-UNITDATA (SGs -> S1) */
|
||||
/* Test SGsAP-UPLINK-UNITDATA (S1 -> SGs)*/
|
||||
/* Test SGSAP-DETACH-IND; detach on S1; expect DETACH-IND on SGs; send DETACH-ACK */
|
||||
/* Test SGsAP-LU-REQ; perform combined attach on S1; expect LU-REQ; acknowlege it */
|
||||
/* Test SGsAP-LU-REQ; perform combined attach on S1; expect LU-REQ; reject it */
|
||||
/* Test SGsAP-MMINFO-REQ; establish SGs association; send it on SGs; expect on S1 */
|
||||
|
||||
/* Test MT SERVICE ABORT; send PAGING; expect SERVICE REQ; send SERVICE ABORT */
|
||||
|
||||
/* Test EPS DETACH */
|
||||
/* Test IMSI DETACH */
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
#!/bin/bash
|
||||
|
||||
BASEDIR=../deps
|
||||
|
||||
. ../gen_links.sh.inc
|
||||
|
||||
DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
|
||||
FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h"
|
||||
FILES+=" TCCEncoding_Functions.ttcn TCCEncoding.cc " # GSM 7-bit coding
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
|
||||
FILES="Socket_API_Definitions.ttcn"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
# Required by MGCP and IPA
|
||||
DIR=$BASEDIR/titan.TestPorts.IPL4asp/src
|
||||
FILES="IPL4asp_Functions.ttcn IPL4asp_PT.cc IPL4asp_PT.hh IPL4asp_PortType.ttcn IPL4asp_Types.ttcn IPL4asp_discovery.cc IPL4asp_protocol_L234.hh"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
|
||||
FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=$BASEDIR/titan.ProtocolModules.MobileL3_v13.4.0/src
|
||||
FILES="MobileL3_CC_Types.ttcn MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types.ttcn MobileL3_MM_Types.ttcn MobileL3_RRM_Types.ttcn MobileL3_SMS_Types.ttcn MobileL3_SS_Types.ttcn MobileL3_Types.ttcn "
|
||||
#FILES+="SS_DataTypes.asn SS_Errors.asn SS_Operations.asn SS_PDU_Defs.asn SS_Protocol.asn SS_Types.ttcn SS_EncDec.cc"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=$BASEDIR/titan.ProtocolModules.SGsAP_13.2.0/src
|
||||
FILES="SGsAP_Types.ttcn"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=../library
|
||||
FILES="Misc_Helpers.ttcn General_Types.ttcn GSM_Types.ttcn Osmocom_Types.ttcn Native_Functions.ttcn Native_FunctionDefs.cc "
|
||||
FILES+="SGsAP_Templates.ttcn SGsAP_CodecPort.ttcn SGsAP_CodecPort_CtrlFunct.ttcn SGsAP_CodecPort_CtrlFunctDef.cc SGsAP_Emulation.ttcn DNS_Helpers.ttcn "
|
||||
FILES+="L3_Templates.ttcn "
|
||||
gen_links $DIR $FILES
|
||||
|
||||
ignore_pp_results
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/sh
|
||||
|
||||
FILES="*.ttcn IPL4asp_PT.cc IPL4asp_discovery.cc Native_FunctionDefs.cc SGsAP_CodecPort_CtrlFunctDef.cc TCCConversion.cc TCCEncoding.cc TCCInterface.cc TELNETasp_PT.cc "
|
||||
|
||||
export CPPFLAGS_TTCN3=""
|
||||
|
||||
../regen-makefile.sh MME_Tests.ttcn $FILES
|
||||
|
||||
sed -i -e 's/^LINUX_LIBS = -lxml2/LINUX_LIBS = -lxml2 -lfftranscode/' Makefile
|
Loading…
Reference in New Issue