/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000-2023 Ericsson Telecom AB // // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v2.0 // which accompanies this distribution, and is available at // https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html /////////////////////////////////////////////////////////////////////////////// // // File: SCCP_selftest.ttcn // Description: SS7 SCCP basic test // according to specification ITU-T SS7 SCCP, ANSI ..., TCC ... // References: ITU-T: Recommendation Q.711-Q.714, // ANSI , // TCC // Rev: R7A // Updated: 2007-04.12 // Contact: http://ttcn.ericsson.se // module SCCP_selftest {//startmodule modulepar { hexstring tsp_own_GT := '0614377760'H; hexstring tsp_remote_GT := '0614375760'H; integer tsp_SSN := 2; //8:MSC 5:MAP see 3.4.2.2/Q.713 octetstring tsp_SIO := '83'O;//SCCP national integer tsp_own_SPC := 461087; // =0x07091E integer tsp_remote_SPC := 461086; // =0x07091D integer tsp_SLS := 0; charstring tsp_sccp_serviceType := "mtp3_itu" }//modulepar import from General_Types all; import from MTP3asp_Types all; import from MTP3asp_PortType all; import from SCCPasp_Types all; import from SCCP_Types all; import from SCCP_Emulation all; //================================================================== // MTPsim component // Description: Simulates two MTP stacks for two MTP3-User // to implement this configuration: // MTPsim includes MTP3/1 and MTP3/2 // MTPsim only receives TRANSFER_req and sends TRANSFER_ind // with the same content // +----------+ +----------+ // |SCCP-userA| <--->|SCCP-userB| = MTC // +----------+ +----------+ // | A | B // +----------+ +----------+ // | SCCP A | <--->| SCCP B | // +----------+ +----------+ // | A | B // +-----------------------------+ // | MTP3 1. | MTP3 2.| = MTP3sim // +----------------------------+ // //================================================================== group MTPsim { type component MTPsim_CT { port MTP3asp_SP_PT MTP_A_PORT port MTP3asp_SP_PT MTP_B_PORT } function MTPsim_EventHandler( ) runs on MTPsim_CT { var ASP_MTP3_TRANSFERreq vl_MTP3_TRANSFERreq; var ASP_MTP3_TRANSFERind vl_MTP3_TRANSFERind alt{ [] MTP_A_PORT.receive( ASP_MTP3_TRANSFERreq:? ) -> value vl_MTP3_TRANSFERreq { MTP_B_PORT.send( t_ASP_MTP3_TRANSFERind( vl_MTP3_TRANSFERreq.sio, vl_MTP3_TRANSFERreq.opc, vl_MTP3_TRANSFERreq.dpc, vl_MTP3_TRANSFERreq.sls, vl_MTP3_TRANSFERreq.data ) ) ; repeat; }//A.receive [] MTP_B_PORT.receive( ASP_MTP3_TRANSFERreq:? ) -> value vl_MTP3_TRANSFERreq { MTP_A_PORT.send( t_ASP_MTP3_TRANSFERind ( vl_MTP3_TRANSFERreq.sio, vl_MTP3_TRANSFERreq.opc, vl_MTP3_TRANSFERreq.dpc, vl_MTP3_TRANSFERreq.sls, vl_MTP3_TRANSFERreq.data )); repeat; }//B.receive }//alt } //MTPsim_EventHandler }//group MTPsim // Main test component with behaviour SCCPuserA andSCCPuserB type component MTC_CT { var SCCP_PAR_Address v_CalledAddress, v_CallingAddress; var integer v_testvalue; var MTPsim_CT vc_MTPsim; var SCCP_CT vc_SCCP_A, vc_SCCP_B; var MSC_SCCP_MTP3_parameters v_BootA; var MSC_SCCP_MTP3_parameters v_BootB; var SCCP_PAR_Connection_Id v_cid_A, v_cid_B; port SCCPasp_PT A_PORT; //SCCPuserA port SCCPasp_PT B_PORT //SCCPuserB } function initBootParams() runs on MTC_CT { v_BootA := { sio:= { ni:= substr(oct2bit(tsp_SIO),0,2), prio:= substr(oct2bit(tsp_SIO),2,2), si:= substr(oct2bit(tsp_SIO),4,4) }, opc:=tsp_own_SPC, dpc:=tsp_remote_SPC, sls:=tsp_SLS, sccp_serviceType:=tsp_sccp_serviceType, ssn:= tsp_SSN }; v_BootB := { sio:= { ni:= substr(oct2bit(tsp_SIO),0,2), prio:= substr(oct2bit(tsp_SIO),2,2), si:= substr(oct2bit(tsp_SIO),4,4) }, opc:=tsp_remote_SPC, dpc:=tsp_own_SPC, sls:=tsp_SLS, sccp_serviceType:=tsp_sccp_serviceType, ssn:= tsp_SSN }; return; } //initBootParams function init() runs on MTC_CT { initBootParams(); log("v_BootA:",v_BootA); log("v_BootB: ",v_BootB); vc_MTPsim:= MTPsim_CT.create; // Protocol Stack A creation & connections: vc_SCCP_A:=SCCP_CT.create; connect(vc_SCCP_A:MTP3_SCCP_PORT,vc_MTPsim:MTP_A_PORT); connect(self:A_PORT,vc_SCCP_A:SCCP_SP_PORT); // Protocol Stack B creation & connections: vc_SCCP_B:=SCCP_CT.create; connect(vc_SCCP_B:MTP3_SCCP_PORT,vc_MTPsim:MTP_B_PORT); connect(self:B_PORT,vc_SCCP_B:SCCP_SP_PORT); // Start stacks: vc_MTPsim.start( MTPsim_EventHandler() ); vc_SCCP_A.start( SCCPStart( v_BootA ) ); // Bootparameters !!! cont here!!! vc_SCCP_B.start( SCCPStart(v_BootB)); log( "init() is done"); }// init function terminate( ) runs on MTC_CT { log( "termitate() started"); /*while( all component.running != true ) { //waits }*/ all component.stop; disconnect(vc_SCCP_A:MTP3_SCCP_PORT, vc_MTPsim:MTP_A_PORT); disconnect(self:A_PORT,vc_SCCP_A:SCCP_SP_PORT); disconnect(vc_SCCP_B:MTP3_SCCP_PORT,vc_MTPsim:MTP_B_PORT); disconnect(self:B_PORT,vc_SCCP_B:SCCP_SP_PORT); log(" all components stopped"); self.stop; } //terminate // function getOddEven returns '0' // if even number of dec digit can be found in GT see Q.713 function getOddEven( in hexstring pl_GT) return bitstring { return int2bit( (lengthof(pl_GT) mod 2) ,1); } function getOddEvenEnc( in hexstring pl_GT) return bitstring { if( (lengthof(pl_GT) mod 2) == 0 ) { return '0010'B;} //even else { return '0001'B;} //odd } //****************************************************************** //function setAddresses_gti0001() runs on MTC_CT // Sets CalledAddress and CallingAddress as a gti001-type address // according to the cfg file. //****************************************************************** function setAddresses_gti0001() runs on MTC_CT { if( (tsp_sccp_serviceType == "mtp3_itu") or (tsp_sccp_serviceType == "mtp3b_itu") or (tsp_sccp_serviceType == "mtp3_ttc") or (tsp_sccp_serviceType == "mtp3b_ttc") ) { v_CalledAddress :={ addressIndicator := { pointCodeIndic := '1'B, ssnIndicator := '1'B, globalTitleIndic := '0001'B, routingIndicator := '0'B },//addressIndicator signPointCode := SCCP_SPC_int2bit(tsp_remote_SPC, tsp_sccp_serviceType, tsp_SIO), // see SCCP_Emulation.ttcn subsystemNumber := tsp_SSN, globalTitle := { gti0001:= { natureOfAddress := '0000011'B, oddeven := getOddEven( tsp_remote_GT ), globalTitleAddress := tsp_remote_GT } }//globalTitle } // v_CalledAddress v_CallingAddress :={ addressIndicator := { pointCodeIndic := '1'B, ssnIndicator := '1'B, globalTitleIndic := '0001'B, routingIndicator := '0'B },//addressIndicator signPointCode := SCCP_SPC_int2bit(tsp_own_SPC, tsp_sccp_serviceType, tsp_SIO), // see SCCP_Emulation.ttcn subsystemNumber := tsp_SSN, globalTitle:= { gti0001 := { natureOfAddress := '0000011'B, oddeven := getOddEven( tsp_own_GT ), globalTitleAddress := tsp_own_GT } }//globalTitle } // v_CallingAddress } else if( (tsp_sccp_serviceType == "mtp3_ansi") or (tsp_sccp_serviceType == "mtp3b_ansi") ) { v_CalledAddress :={ addressIndicator := { pointCodeIndic := '1'B, ssnIndicator := '1'B, globalTitleIndic := '0001'B, routingIndicator := '0'B },//addressIndicator signPointCode := SCCP_SPC_int2bit(tsp_remote_SPC, tsp_sccp_serviceType, tsp_SIO), // see SCCP_Emulation.ttcn subsystemNumber := tsp_SSN, globalTitle := { gti0011:= { translationType := int2oct(7,1), encodingScheme := getOddEvenEnc( tsp_remote_GT ), numberingPlan := '0111'B, //ISDN/mobile numbering plan, see T1.112.3-2001/3.4.2.3.1 globalTitleAddress:= tsp_remote_GT } }//globalTitle } // v_CalledAddress v_CallingAddress :={ addressIndicator := { pointCodeIndic := '1'B, ssnIndicator := '1'B, globalTitleIndic := '0001'B, routingIndicator := '0'B },//addressIndicator signPointCode := SCCP_SPC_int2bit(tsp_remote_SPC, tsp_sccp_serviceType, tsp_SIO), // see SCCP_Emulation.ttcn subsystemNumber := tsp_SSN, globalTitle := { gti0011:= { translationType := int2oct(7,1), encodingScheme := getOddEvenEnc( tsp_own_GT ), numberingPlan := '0111'B, //ISDN/mobile numbering plan, see T1.112.3-2001/3.4.2.3.1 globalTitleAddress:= tsp_own_GT } }//globalTitle } // v_CallingAddress }//if else { log( "wrong tsp_sccp_serviceType ->exit "); setverdict( fail ); } }//setAddresses_gti001 function f_SendAndReceive1N_UNITDATA(in octetstring pl_userdata) runs on MTC_CT { var ASP_SCCP_N_UNITDATA_ind vl_N_UNITDATA_ind; timer TL_timer:= 40.0; TL_timer.start; log("A_PORT.send follows"); log("Addresses:",v_CalledAddress, v_CallingAddress); A_PORT.send( t_ASP_N_UNITDATA_req( v_CalledAddress, v_CallingAddress, '00000001'B, //sequence control '00000001'B, //return option pl_userdata, omit ) ); log("A_PORT.send executed"); alt { [] B_PORT.receive( tr_ASP_N_UNITDATA_ind ) -> value vl_N_UNITDATA_ind { if( (vl_N_UNITDATA_ind.calledAddress == v_CalledAddress ) and (vl_N_UNITDATA_ind.callingAddress == v_CallingAddress) and (vl_N_UNITDATA_ind.userData == pl_userdata) ) { log("Correct CalledAddress, CallingAddress and userData received, data are correct"); setverdict(pass); } else { log("Some data corrupted"); log("Original data:", v_CalledAddress, v_CallingAddress, pl_userdata); setverdict( fail ); } }; [] TL_timer.timeout { setverdict( fail ); log("Timeout...."); }; } //alt TL_timer.stop; }//f_SendAndReceive1N_UNITDATA /**************************************************** Connection Oriented Part ****************************************************/ /**************************************************** function f_connect Establishes a connection (Sends an ASP_SCCP_N_CONNECT_req on A_PORT and waits for N_CONNECT_ind on B_PORT. If it is received, it sends back an ASP_SCCP_N_CONNECT_res on B_PORT and waits for N_CONNECT_cfm on A_PORT) ****************************************************/ function f_connect() runs on MTC_CT return boolean { var ASP_SCCP_N_CONNECT_ind vl_N_CONNECT_ind; var ASP_SCCP_N_CONNECT_cfm vl_N_CONNECT_cfm; setverdict(none); v_cid_A := 13; timer TL_timer:= 40.0; TL_timer.start; // A Sends ASP_SCCP_N_CONNECT_req , receives A_PORT.send( t_ASP_N_CONNECT_req( v_CalledAddress, v_CallingAddress, omit, //expeditedDataSel omit, //QoS omit, //userData v_cid_A, omit //importance ) ); alt { [] B_PORT.receive( tr_ASP_N_CONNECT_ind ) -> value vl_N_CONNECT_ind { v_cid_B := vl_N_CONNECT_ind.connectionId; B_PORT.send( t_ASP_N_CONNECT_res( omit,// respondingAddress omit,//expeditedDataSel omit,//qualityOfService omit, //userData v_cid_B, omit //importance )); } [] B_PORT.receive { log( "unexpected asp received for ASP_SCCP_N_CONNECT_req, failed"); setverdict( fail ); return false; } [] TL_timer.timeout { setverdict( pass ); log("Timeout...."); return false; } } // receives ASP_SCCP_N_CONNECT_cfm alt { [] A_PORT.receive( tr_ASP_N_CONNECT_cfm ) -> value vl_N_CONNECT_cfm { setverdict( pass ); log("f_connect finished successfully"); return true; } [] TL_timer.timeout { setverdict( pass ); log("Timeout...."); return false; } }// alt log("f_connect finished"); return false; }//f_connect /**************************************************** function f_send Sends an ASP_SCCP_N_DATA_req on A_PORT and waits for answer in B_PORT ****************************************************/ function f_send(in octetstring pl_userdata) runs on MTC_CT { var ASP_SCCP_N_DATA_ind vl_N_DATA_ind; timer TL_timer:= 120.0; TL_timer.start; A_PORT.send( t_ASP_N_DATA_req ( pl_userdata, v_cid_A, omit) ) ; alt { [] B_PORT.receive( tr_ASP_N_DATA_ind ) -> value vl_N_DATA_ind { if( vl_N_DATA_ind.userData == pl_userdata ) { log( "userData received correctly" ); setverdict( pass ); } else { log("user data mismatch error in f_send()") setverdict(fail); } }//B_PORT.receive( tr_ASP_N_DATA_ind ) [] B_PORT.receive { log( "unexpected asp received for ASP_SCCP_N_DATA_req, failed"); setverdict( fail ); } [] TL_timer.timeout { setverdict( pass ); log("Timeout...."); } } //alt }//f_send //f_disconnect with timeout function f_disconnect( ) runs on MTC_CT { var ASP_SCCP_N_DISCONNECT_ind vl_N_DISCONNECT_ind; timer TL_timer:= 5.0; TL_timer.start; A_PORT.send(t_ASP_N_DISCONNECT_req( omit, // respondingAddress 0, //reason : end user originated, see 3.11/Q.713 omit, //userData v_cid_A, omit )) alt { [] B_PORT.receive(tr_ASP_N_DISCONNECT_ind) -> value vl_N_DISCONNECT_ind { setverdict( pass ); } [] B_PORT.receive { log("unexpected asp received on B_PORT instead of ASP_SCCP_N_DISCONNECT_ind"); //repeat; setverdict(fail); } [] TL_timer.timeout { setverdict( fail ); log("Timeout...."); }; }//alt //give time for inner release complete (rlc): alt { [] TL_timer.timeout { setverdict( pass ); log("Stopped with expected timeout"); }; } }//f_disconnect //=================================================== // Testcases //=================================================== /**************************************************** tc_ConnlessSendingShortASP Sends a 300 octet long userdata in one ASP_SCCP_N_UNITDATA_req and receives it in one ASP_SCCP_N_UNITDATA_req. SCCP transfers information in udp or (forced) xudp packets. ****************************************************/ testcase tc_ConnlessSendingShortASP() runs on MTC_CT { var octetstring vl_userdata; init(); setAddresses_gti0001(); vl_userdata :='12345678901234567890'O; f_SendAndReceive1N_UNITDATA( vl_userdata ); terminate(); } //tc_ConnlessSendingShortASP /**************************************************** tc_ConnlessSendingLongASP Sends a 300 octet long userdata in one ASP_SCCP_N_UNITDATA_req and receives it in one ASP_SCCP_N_UNITDATA_req. It is used for segmentation and reassembly. SCCP transfers information in xudp packets ****************************************************/ testcase tc_ConnlessSendingLongASP() runs on MTC_CT { var octetstring vl_userdata; var integer vl_i; init(); setAddresses_gti0001(); vl_userdata := ''O; for(vl_i:=0;vl_i<30;vl_i:=vl_i+1) { vl_userdata := vl_userdata &'12345678901234567890'O; } f_SendAndReceive1N_UNITDATA( vl_userdata ); terminate(); }//tc_ConnlessSendingLongASP /**************************************************** tc_ConnOrientedShortASPSending ****************************************************/ testcase tc_ConnOrientedShortASPSending() runs on MTC_CT { var octetstring vl_userdata; init(); setAddresses_gti0001(); vl_userdata := '12345678901234567890'O; if(f_connect( )) { f_send(vl_userdata); f_disconnect(); } terminate(); } /**************************************************** tc_ConnOrientedLongASPSending ****************************************************/ testcase tc_ConnOrientedLongASPSending() runs on MTC_CT { var octetstring vl_userdata; var integer vl_i; init(); setAddresses_gti0001(); vl_userdata := ''O; for(vl_i:=0;vl_i<30;vl_i:=vl_i+1) { vl_userdata := vl_userdata &'12345678901234567890'O; } if(f_connect( )) { f_send(vl_userdata); //f_SendAndReceive1N_UNITDATA( vl_userdata ); f_disconnect(); } terminate(); } /**************************************************** CONTROL ****************************************************/ control { execute( tc_ConnlessSendingShortASP() ); execute( tc_ConnlessSendingLongASP() ); execute( tc_ConnOrientedShortASPSending()); execute( tc_ConnOrientedLongASPSending()); } }//module