mme: initial skeleton for MME / SGsAP tetss

Change-Id: Idbd54838daaf12acccc3253dc4278de75eaaaf31
This commit is contained in:
Harald Welte 2019-06-23 11:04:12 +02:00 committed by laforge
parent 97ae972c4a
commit b8a4ac80a6
5 changed files with 385 additions and 0 deletions

View File

@ -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;

118
mme/MME_Tests.ttcn Normal file
View File

@ -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);
}
}

210
mme/MME_Tests_SGsAP.ttcn Normal file
View File

@ -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 */
}

40
mme/gen_links.sh Executable file
View File

@ -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

9
mme/regen_makefile.sh Executable file
View File

@ -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