From 9adf57b5acd0c7f7d92b9a8f5b0105df46d385e5 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 10 Jan 2020 12:33:44 +0100 Subject: [PATCH] Add SCCP_Tests_RAW for testing the actual SCCP implementation Using SCCP_Tests_RAW.ttcn we can trasnceive decoded MTP3 primitives containing decoded SCCP messages against a remote SCCP implementation. Related: OS#4343 Change-Id: I07c43cfac9cdbdeccf102cd08309ca9ec64968cc --- sccp/SCCP_CodecPort.ttcn | 73 ++++++++++++++++ sccp/SCCP_Tests.cfg | 1 + sccp/SCCP_Tests_RAW.ttcn | 174 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 248 insertions(+) create mode 100644 sccp/SCCP_CodecPort.ttcn create mode 100644 sccp/SCCP_Tests_RAW.ttcn diff --git a/sccp/SCCP_CodecPort.ttcn b/sccp/SCCP_CodecPort.ttcn new file mode 100644 index 000000000..838517a0d --- /dev/null +++ b/sccp/SCCP_CodecPort.ttcn @@ -0,0 +1,73 @@ +module SCCP_CodecPort { + +/* Simple SCCP Codec Port, translating between raw MTP3 primitives with + * octetstring payload towards the MTP3 provider, and MTP3-SCCP primitives + * which carry the decoded SCCP data types as payload. + * + * (C) 2019 by Harald Welte + * All rights reserved. + * + * Released under the terms of GNU General Public License, Version 2 or + * (at your option) any later version. + */ + +import from General_Types all; +import from Osmocom_Types all; + +import from MTP3asp_Types all; +import from MTP3asp_PortType all; +import from SCCP_Types all; + +/* MTP3asp_Types.Types.MessageTypes.ASP_MTP3_TRANSFERind with PDU_SCCP instead of octetstring */ +type record SCCP_MTP3_TRANSFERind { + MTP3_Field_sio sio, + integer opc, + integer dpc, + integer sls, + PDU_SCCP data +}; + +/* MTP3asp_Types.Types.MessageTypes.ASP_MTP3_TRANSFERreq with PDU_SCCP instead of octetstring */ +type record SCCP_MTP3_TRANSFERreq { + MTP3_Field_sio sio, + integer opc, + integer dpc, + integer sls, + PDU_SCCP data +}; + +private function f_dec_TRANSFERind(in ASP_MTP3_TRANSFERind pin, out SCCP_MTP3_TRANSFERind pout) { + pout.sio := pin.sio; + pout.opc := pin.opc; + pout.dpc := pin.dpc; + pout.sls := pin.sls; + pout.data := dec_PDU_SCCP(pin.data); + //port.setstate(0); +} with {extension "prototype(fast)" } + + +private function f_enc_TRANSFERreq(in SCCP_MTP3_TRANSFERreq pin, out ASP_MTP3_TRANSFERreq pout) { + pout.sio := pin.sio; + pout.opc := pin.opc; + pout.dpc := pin.dpc; + pout.sls := pin.sls; + pout.data := enc_PDU_SCCP(pin.data); + //port.setstate(0); +} with {extension "prototype(fast)" } + +type port SCCP_CODEC_PT message { + out SCCP_MTP3_TRANSFERreq; + in SCCP_MTP3_TRANSFERind, + ASP_MTP3_PAUSE, + ASP_MTP3_RESUME, + ASP_MTP3_STATUS; +} with { extension "internal user MTP3asp_PT + out(SCCP_MTP3_TRANSFERreq -> ASP_MTP3_TRANSFERreq: function(f_enc_TRANSFERreq)) + in(ASP_MTP3_TRANSFERind -> SCCP_MTP3_TRANSFERind: function(f_dec_TRANSFERind); + ASP_MTP3_PAUSE -> ASP_MTP3_PAUSE: simple; + ASP_MTP3_RESUME -> ASP_MTP3_RESUME: simple; + ASP_MTP3_STATUS -> ASP_MTP3_STATUS: simple)" +} + + +} diff --git a/sccp/SCCP_Tests.cfg b/sccp/SCCP_Tests.cfg index ab69a2db0..8e51327fc 100644 --- a/sccp/SCCP_Tests.cfg +++ b/sccp/SCCP_Tests.cfg @@ -16,3 +16,4 @@ [EXECUTE] SCCP_Tests.control +SCCP_Tests_RAW.control diff --git a/sccp/SCCP_Tests_RAW.ttcn b/sccp/SCCP_Tests_RAW.ttcn new file mode 100644 index 000000000..78ce80fa1 --- /dev/null +++ b/sccp/SCCP_Tests_RAW.ttcn @@ -0,0 +1,174 @@ +/* (C) 2019 by Harald Welte + * All Rights Reserved + * + * The idea is that these tests are executed against sccp_demo_user from + * libosmo-sccp.git in server mode. + * + * 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 SCCP_Tests_RAW { + +import from General_Types all; +import from Osmocom_Types all; + +import from M3UA_Emulation all; + +import from SCCP_Types all; +import from SCCPasp_Types all; +import from SCCP_Templates all; +import from SCCP_Emulation all; +import from SCCP_CodecPort all; + +import from TELNETasp_PortType all; +import from Osmocom_VTY_Functions all; + +import from SCCP_Tests all; + +type component SCCP_Test_RAW_CT { + /* VTY to sccp_demo_user (not used yet) */ + port TELNETasp_PT SCCP_DEMO_USER_VTY; + + /* SCCP raw port runs on top of M3UA Emulation. + * "System Under Test" is libosmo-sccp's sccp_demo_user example program. */ + var M3UA_CT vc_M3UA; + port SCCP_CODEC_PT MTP3; + + var MSC_SCCP_MTP3_parameters g_param; +} + +private function f_init_raw(SCCP_Configuration cfg) runs on SCCP_Test_RAW_CT { + g_param := { + sio := { + ni := substr(oct2bit(cfg.sio),0,2), + prio := substr(oct2bit(cfg.sio),2,2), + si := substr(oct2bit(cfg.sio),4,4) + }, + opc := cfg.own_pc, + dpc := cfg.peer_pc, + sls := 0, + sccp_serviceType := cfg.sccp_service_type, + ssn := cfg.own_ssn + }; + + map(self:SCCP_DEMO_USER_VTY, system:SCCP_DEMO_USER_VTY); + f_vty_set_prompts(SCCP_DEMO_USER_VTY); + f_vty_transceive(SCCP_DEMO_USER_VTY, "enable"); + + /* Create and connect test components */ + vc_M3UA := M3UA_CT.create; + connect(self:MTP3, vc_M3UA:MTP3_SP_PORT); + map(vc_M3UA:SCTP_PORT, system:sctp); + + vc_M3UA.start(f_M3UA_Emulation(cfg.sctp_addr)); +} + +private function f_cleanup() runs on SCCP_Test_RAW_CT { + all component.stop; + unmap(vc_M3UA:SCTP_PORT, system:sctp); + disconnect(vc_M3UA:MTP3_SP_PORT, self:MTP3); + self.stop +} + +/* connection oriented SCCP */ +const SCCP_param_ProtocolClass c_class2 := { class:='0010'B, messageHandling:='0000'B };//class 2 + +function ts_SCCP_CR(OCT3 source_lref, SCCP_PAR_Address calling, SCCP_PAR_Address called) +return template (value) PDU_SCCP { + var SCCP_param_CPartyAddressEnc calling_enc := ConvertASPAddressToEncodedAddress_itu(calling); + + var template (value) PDU_SCCP ret := { + connrequest := { + messageType := cr, + sourceLocRef := source_lref, + protClass := c_class2, + pointer1 := 2, + pointer2 := 0, /* overwritten */ + calledPAddress := ConvertASPAddressToEncodedAddress_itu(called), + optionalPart := { + credit := omit, + callingPAddress := { + paramName := con_SCCP_cgPA, + paramLength := calling_enc.paramLength, /* overwritten */ + addr := calling_enc.addr + }, + data := omit, + hopCounter := omit, + importance := omit + }, + eop := { paramName:= con_SCCP_eop } + } + } + return ret; +} + +template (present) PDU_SCCP tr_SCCP_CC(template (present) OCT3 dest_lref, + template (present) OCT3 source_lref) := { + connconfirm := { + messageType := cc, + destLocRef := dest_lref, + sourceLocRef := source_lref, + protClass := c_class2, + pointer1 := ?, + optionalPart := *, + eop := * + } +} + +private function f_send_sccp(template PDU_SCCP sccp) runs on SCCP_Test_RAW_CT { + var SCCP_MTP3_TRANSFERreq tx := { + sio := g_param.sio, + opc := g_param.opc, + dpc := g_param.dpc, + sls := g_param.sls, + data := valueof(sccp) + }; + MTP3.send(tx); +} + +private function f_exp_sccp(template PDU_SCCP sccp) runs on SCCP_Test_RAW_CT { + var SCCP_MTP3_TRANSFERind rx; + var template SCCP_MTP3_TRANSFERind exp := { + sio := g_param.sio, + opc := g_param.dpc, + dpc := g_param.opc, + sls := g_param.sls, + data := sccp + }; + timer T := 10.0; + T.start; + alt { + [] MTP3.receive(exp) -> value rx { + setverdict(pass); + } + [] MTP3.receive { + setverdict(fail, "Unexpected MTP/SCCP received"); + } + [] T.timeout { + setverdict(fail, "Timeout waiting for ", exp); + } + } +} + +/* Verify sccp_demo_user answers a CR with a CC for PC and SSN set up to echo back */ +testcase TC_cr_cc() runs on SCCP_Test_RAW_CT { + var SCCP_PAR_Address calling, called; + called := valueof(ts_SccpAddr_PC_SSN(sccp_cfg[0].peer_pc, sccp_cfg[0].peer_ssn, + sccp_cfg[0].sio, sccp_cfg[0].sccp_service_type)); + calling := valueof(ts_SccpAddr_PC_SSN(sccp_cfg[0].own_pc, sccp_cfg[0].own_ssn, + sccp_cfg[0].sio, sccp_cfg[0].sccp_service_type)); + f_init_raw(sccp_cfg[0]); + f_sleep(1.0); + f_send_sccp(ts_SCCP_CR('000001'O, calling, called)); + f_exp_sccp(tr_SCCP_CC('000001'O, ?)); +} + +control { + execute( TC_cr_cc() ); +} + + +}