From b3414b217219283666e01928e0b193211d2b3159 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 23 Nov 2017 18:22:10 +0100 Subject: [PATCH] ipa: First version that emulates both MSC and BSC up to ASSIGNMENT REQ --- ipa/BSC_MS_ConnectionHandler.ttcn | 105 +++++++++++++++++++++ ipa/BSC_MS_Simulation.ttcn | 77 ++++++++++++++++ ipa/IPA_Test.ttcn | 148 +++++++++++++++--------------- ipa/MSC_ConnectionHandler.ttcn | 2 +- ipa/MSC_Simulation.ttcn | 59 ++++++++++++ ipa/gen_links.sh | 2 +- library/BSSMAP_Emulation.ttcn | 77 +++++++++++++++- library/BSSMAP_Templates.ttcn | 140 +++++++++++++++++++++++++++- library/IPA_Emulation.ttcn | 56 ++++++++++- 9 files changed, 581 insertions(+), 85 deletions(-) create mode 100644 ipa/BSC_MS_ConnectionHandler.ttcn create mode 100644 ipa/BSC_MS_Simulation.ttcn create mode 100755 ipa/MSC_Simulation.ttcn diff --git a/ipa/BSC_MS_ConnectionHandler.ttcn b/ipa/BSC_MS_ConnectionHandler.ttcn new file mode 100644 index 000000000..443babee6 --- /dev/null +++ b/ipa/BSC_MS_ConnectionHandler.ttcn @@ -0,0 +1,105 @@ +module BSC_MS_ConnectionHandler { + +import from General_Types all; +import from Osmocom_Types all; +import from SCCPasp_Types all; +import from BSSAP_Types all; +import from BSSMAP_Emulation all; +import from BSSMAP_Templates all; + +import from MobileL3_Types all; +import from MobileL3_CommonIE_Types all; +import from L3_Templates all; + +/* this component represents a single subscriber connection at the MSC. + * There is a 1:1 mapping between SCCP connections and BSSAP_ConnHdlr components. + * We inherit all component variables, ports, functions, ... from BSSAP_ConnHdlr */ +type component BSC_MS_ConnHdlr extends BSSAP_ConnHdlr { + /* SCCP Connecction Identifier for the underlying SCCP connection */ + var integer g_sccp_conn_id; +} + +/* Callback function from general BSSMAP_Emulation whenever a new incoming + * SCCP connection arrivces. Must create + start a new component */ +private function CreateCallback(ASP_SCCP_N_CONNECT_ind conn_ind) +runs on BSSMAP_Emulation_CT return BSSAP_ConnHdlr { + log("Incoming SCCP Connection on BSC ?!?"); + self.stop; +} + +/* Callback function from general BSSMAP_Emulation whenever a connectionless + * BSSMAP message arrives. Can retunr a PDU_BSSAP that should be sent in return */ +private function UnitdataCallback(PDU_BSSAP bssap) +runs on BSSMAP_Emulation_CT return template PDU_BSSAP { + var template PDU_BSSAP resp := omit; + + if (match(bssap, tr_BSSMAP_Reset)) { + resp := ts_BSSMAP_ResetAck; + } + + return resp; +} + +const BssmapOps BSC_MS_BssmapOps := { + create_cb := refers(CreateCallback), + unitdata_cb := refers(UnitdataCallback) +} + + +function f_gen_cl3(hexstring imsi) return PDU_BSSAP { + var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(imsi)); + var PDU_ML3_MS_NW l3 := valueof(ts_CM_SERV_REQ('0001'B, mi)); + var BSSMAP_IE_CellIdentifier cell_id := valueof(ts_CellID_LAC_CI(23, 42)); + var PDU_BSSAP bssap := valueof(ts_BSSMAP_ComplL3(cell_id, enc_PDU_ML3_MS_NW(l3))); + return bssap; +} + +/* main function processing various incoming events */ +function main(SCCP_PAR_Address sccp_addr_own, SCCP_PAR_Address sccp_addr_remote) +runs on BSC_MS_ConnHdlr { + var PDU_BSSAP bssap; + + log("Starting main of BSC_MS_ConnHdlr"); + + /* generate and send the Complete Layer3 Info */ + bssap := f_gen_cl3('901770123456789'H); + + var BSSAP_Conn_Req creq := { + addr_peer := sccp_addr_remote, + addr_own := sccp_addr_own, + bssap := bssap + } + BSSAP.send(creq); + + while (true) { + alt { + /* new SCCP-level connection indication from BSC */ + [] BSSAP.receive(tr_BSSMAP_AssignmentCmd) -> value bssap { + /* TODO: Read CIC */ + /* respond with ASSIGNMENT COMPL */ + BSSAP.send(ts_BSSMAP_AssignmentComplete(bssap.pdu.bssmap.assignmentRequest.circuitIdentityCode)); + } + /* TODO: CLEAR REQUEST from BSS */ + /* CLEAR COMMAND from MSC; respond with CLEAR COMPLETE) */ + [] BSSAP.receive(tr_BSSMAP_ClearCommand) -> value bssap { + BSSAP.send(ts_BSSMAP_ClearComplete); + /* FIXME: local release? */ + } + + [] BSSAP.receive(tr_BSSAP_DTAP) -> value bssap { + var PDU_ML3_MS_NW l3 := dec_PDU_ML3_MS_NW(bssap.pdu.dtap); + log("Unhandled DTAP ", l3); + } + + [] BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND) { + self.stop; + } + + [] BSSAP.receive(PDU_BSSAP:?) -> value bssap { + log("Received unhandled SCCP-CO: ", bssap); + } + } + } +} + +} diff --git a/ipa/BSC_MS_Simulation.ttcn b/ipa/BSC_MS_Simulation.ttcn new file mode 100644 index 000000000..c33e84847 --- /dev/null +++ b/ipa/BSC_MS_Simulation.ttcn @@ -0,0 +1,77 @@ +module BSC_MS_Simulation { + +import from IPL4asp_Types all; + +import from IPA_Emulation all; + +import from SCCP_Types all; +import from SCCPasp_Types all; +import from SCCP_Emulation all; + +import from BSSMAP_Emulation all; + +import from BSC_MS_ConnectionHandler all; + +type component BSC_CT { + /* component references */ + var IPA_Emulation_CT vc_IPA; + var SCCP_CT vc_SCCP; + var BSSMAP_Emulation_CT vc_BSSMAP; + /* test port to SCCP emulation */ + port SCCPasp_PT SCCP; + + var SCCP_PAR_Address g_sccp_addr_own; + var SCCP_PAR_Address g_sccp_addr_remote; +} + +function main(charstring remote_ip, PortNumber remote_port, + charstring local_ip, PortNumber local_port, + MSC_SCCP_MTP3_parameters sccp_pars, + SCCP_PAR_Address sccp_addr_own, + SCCP_PAR_Address sccp_addr_remote) runs on BSC_CT +{ + g_sccp_addr_own := sccp_addr_own; + g_sccp_addr_remote := sccp_addr_remote; + + /* create components */ + vc_IPA := IPA_Emulation_CT.create; + vc_SCCP := SCCP_CT.create; + vc_BSSMAP := BSSMAP_Emulation_CT.create; + + map(vc_IPA:IPA_PORT, system:IPA_CODEC_PT); + + /* connect MTP3 service provider (IPA) to lower side of SCCP */ + connect(vc_IPA:MTP3_SP_PORT, vc_SCCP:MTP3_SCCP_PORT); + + /* connect BSSNAP dispatcher to upper side of SCCP */ + connect(vc_BSSMAP:SCCP, vc_SCCP:SCCP_SP_PORT); + + vc_IPA.start(IPA_Emulation.main_client(remote_ip, remote_port, local_ip, local_port)); + vc_SCCP.start(SCCPStart(sccp_pars)); + vc_BSSMAP.start(BSSMAP_Emulation.main(BSC_MS_BssmapOps)); + + while (true) { + timer T := 5.0; + T.start; + T.timeout; + f_start_BSC_MS(); + //vc_IPA.MTP3_SP_PORT.send(t_ASP_MTP3_TRANSFERreq_sccp('83'O, 1, 2, 0, '012345'O)); + } + + vc_IPA.done; + vc_BSSMAP.done; + vc_SCCP.done +} + +function f_start_BSC_MS() runs on BSC_CT { + var BSC_MS_ConnHdlr vc_conn; + + /* start new component */ + vc_conn := BSC_MS_ConnHdlr.create; + /* connect client BSSAP port to BSSAP dispatcher */ + connect(vc_conn:BSSAP, vc_BSSMAP:CLIENT); + /* start component */ + vc_conn.start(BSC_MS_ConnectionHandler.main(g_sccp_addr_own, g_sccp_addr_remote)); +} + +} diff --git a/ipa/IPA_Test.ttcn b/ipa/IPA_Test.ttcn index 4e87fa682..c8b820534 100644 --- a/ipa/IPA_Test.ttcn +++ b/ipa/IPA_Test.ttcn @@ -1,48 +1,58 @@ module IPA_Test { +import from Osmocom_Types all; + import from IPL4asp_Types all; import from IPA_Emulation all; +import from MTP3asp_Types all; + import from SCCP_Types all; import from SCCPasp_Types all; import from SCCP_Emulation all; -import from MobileL3_Types all; -import from MobileL3_CommonIE_Types all; -import from L3_Templates all; +import from MSC_Simulation all; +import from BSC_MS_Simulation all; -import from BSSAP_Types all; -import from BSSMAP_Templates all; +const integer NUM_MSC := 1; +const integer NUM_BSC := 1; + +type record BscState { + BSC_CT BSC, + MSC_SCCP_MTP3_parameters sccp_pars, + SCCP_PAR_Address sccp_addr_own, + SCCP_PAR_Address sccp_addr_peer +} + +type record MscState { + MSC_CT MSC, + MSC_SCCP_MTP3_parameters sccp_pars, + SCCP_PAR_Address sccp_addr_own +} type component test_CT { - /* component references */ - var IPA_Emulation_CT vc_IPA; - var SCCP_CT vc_SCCP; - /* test port to SCCP emulation */ - port SCCPasp_PT SCCP; + var MscState msc[NUM_MSC]; + var BscState bsc[NUM_BSC]; var boolean g_initialized := false; - var octetstring g_sio; - var MSC_SCCP_MTP3_parameters g_sccp_pars; - var SCCP_PAR_Address g_sccp_addr_own, g_sccp_addr_peer; - - var ConnectionId g_ipa_conn_id := -1; + var octetstring g_sio := '83'O; } modulepar { - PortNumber mp_local_port := 0; - charstring mp_local_ip := "127.0.0.1"; - PortNumber mp_remote_port := 3002; - charstring mp_remote_ip := "127.0.0.1"; + PortNumber mp_bsc_port := 49999; + charstring mp_bsc_ip := "127.0.0.1"; + + PortNumber mp_msc_port := 5000; + charstring mp_msc_ip := "127.0.0.1"; charstring mp_sccp_service_type := "mtp3_itu"; - integer mp_own_pc := 196; - integer mp_own_ssn := 254; + integer mp_bsc_pc := 196; + integer mp_bsc_ssn := 254; - integer mp_peer_pc := 185; /* 0.23.1 */ - integer mp_peer_ssn := 254; + integer mp_msc_pc := 185; /* 0.23.1 */ + integer mp_msc_ssn := 254; } /* construct a SCCP_PAR_Address with just PC + SSN and no GT */ @@ -59,76 +69,62 @@ template (value) SCCP_PAR_Address ts_SccpAddr_PC_SSN(integer pc, integer ssn) := globalTitle := omit } - -function f_gen_cl3() return PDU_BSSAP { - var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV('901770123456789'H)); - var PDU_ML3_MS_NW l3 := valueof(ts_CM_SERV_REQ('0001'B, mi)); - var BSSMAP_IE_CellIdentifier cell_id := valueof(ts_CellID_LAC_CI(23, 42)); - var PDU_BSSAP bssap := valueof(ts_BSSMAP_ComplL3(cell_id, enc_PDU_ML3_MS_NW(l3))); - return bssap; +template MTP3_Field_sio ts_sio(octetstring sio_in) := { + ni := substr(oct2bit(sio_in),0,2), + prio := substr(oct2bit(sio_in),2,2), + si := substr(oct2bit(sio_in),4,4) } -function f_send_bssap_cc(PDU_BSSAP bssap) runs on test_CT { - var ASP_SCCP_N_CONNECT_req prim; - prim := valueof(t_ASP_N_CONNECT_req(g_sccp_addr_peer, g_sccp_addr_own, omit, omit, - enc_PDU_BSSAP(bssap), 23, omit)); - SCCP.send(prim); +template MSC_SCCP_MTP3_parameters ts_SCCP_Pars(octetstring sio, integer opc, integer dpc, + integer local_ssn) := { + sio := ts_sio(sio), + opc := opc, + dpc := dpc, + sls := 0, + sccp_serviceType := mp_sccp_service_type, + ssn := local_ssn +}; + +function f_init_BscState(inout BscState bsc_st, integer opc, integer dpc, integer local_ssn, integer remote_ssn) +runs on test_CT { + bsc_st.sccp_pars := valueof(ts_SCCP_Pars(g_sio, opc, dpc, local_ssn)); + bsc_st.sccp_addr_own := valueof(ts_SccpAddr_PC_SSN(opc, local_ssn)); + bsc_st.sccp_addr_peer := valueof(ts_SccpAddr_PC_SSN(dpc, remote_ssn)); } -function init_pars() runs on test_CT { - g_sio := '83'O; - g_sccp_pars := { - sio := { - ni := substr(oct2bit(g_sio),0,2), - prio := substr(oct2bit(g_sio),2,2), - si := substr(oct2bit(g_sio),4,4) - }, - opc := mp_own_pc, - dpc := mp_peer_pc, - sls := 0, - sccp_serviceType := mp_sccp_service_type, - ssn := mp_own_ssn - }; - g_sccp_addr_own := valueof(ts_SccpAddr_PC_SSN(mp_own_pc, mp_own_ssn)); - g_sccp_addr_peer := valueof(ts_SccpAddr_PC_SSN(mp_peer_pc, mp_peer_ssn)); +function f_init_MscState(inout MscState msc_st, integer opc, integer dpc, integer local_ssn, integer remote_ssn) +runs on test_CT { + msc_st.sccp_pars := valueof(ts_SCCP_Pars(g_sio, opc, dpc, local_ssn)); + msc_st.sccp_addr_own := valueof(ts_SccpAddr_PC_SSN(opc, local_ssn)); } -private function f_init() runs on test_CT { - var Result res; +function f_init() runs on test_CT { + var integer i; - if (g_initialized == true) { - return; + for (i := 0; i < NUM_MSC; i := i+1) { + f_init_MscState(msc[i], mp_msc_pc +i, mp_bsc_pc, mp_msc_ssn, mp_bsc_ssn); + msc[i].MSC := MSC_CT.create; + msc[i].MSC.start(MSC_Simulation.main(mp_msc_ip, mp_msc_port + i, msc[i].sccp_pars, msc[i].sccp_addr_own)); } - g_initialized := true; - init_pars(); + for (i := 0; i < NUM_BSC; i := i+1) { + f_init_BscState(bsc[i], mp_bsc_pc +i, mp_msc_pc, mp_bsc_ssn, mp_msc_ssn); + bsc[i].BSC := BSC_CT.create; + bsc[i].BSC.start(BSC_MS_Simulation.main(mp_msc_ip, mp_msc_port, mp_bsc_ip, mp_bsc_port+i, + bsc[i].sccp_pars, bsc[i].sccp_addr_own, + bsc[i].sccp_addr_peer)); + } - /* create components */ - vc_IPA := IPA_Emulation_CT.create; - vc_SCCP := SCCP_CT.create; - - map(vc_IPA:IPA_PORT, system:IPA_CODEC_PT); - - /* connect MTP3 service provider (IPA) to lower side of SCCP */ - connect(vc_IPA:MTP3_SP_PORT, vc_SCCP:MTP3_SCCP_PORT); - - /* connect us to upper side of SCCP */ - connect(self:SCCP, vc_SCCP:SCCP_SP_PORT); - - vc_IPA.start(IPA_Emulation.ScanEvents()); - vc_SCCP.start(SCCPStart(g_sccp_pars)); - - //IPA_Emulation.f_connect(mp_remote_ip, mp_remote_port, mp_local_ip, mp_local_port); } testcase TC_recv_dump() runs on test_CT { f_init(); - var PDU_BSSAP bssap := f_gen_cl3(); - f_send_bssap_cc(bssap); + //var PDU_BSSAP bssap := f_gen_cl3(); + //f_send_bssap_cc(bssap); while (true) { - SCCP.receive; + //SCCP.receive; } } diff --git a/ipa/MSC_ConnectionHandler.ttcn b/ipa/MSC_ConnectionHandler.ttcn index 0d7cd20bd..9cec55628 100644 --- a/ipa/MSC_ConnectionHandler.ttcn +++ b/ipa/MSC_ConnectionHandler.ttcn @@ -52,7 +52,7 @@ const BssmapOps MSC_BssmapOps := { /* main function processing various incoming events */ function main(integer connection_id, integer timeslot) runs on MSC_ConnHdlr { g_sccp_conn_id := connection_id; - g_e1_timeslot := timeslot + g_e1_timeslot := 1; /* FIXME */ while (true) { var PDU_BSSAP bssap; diff --git a/ipa/MSC_Simulation.ttcn b/ipa/MSC_Simulation.ttcn new file mode 100755 index 000000000..8c9418845 --- /dev/null +++ b/ipa/MSC_Simulation.ttcn @@ -0,0 +1,59 @@ +module MSC_Simulation { + +import from IPL4asp_Types all; + +import from IPA_Emulation all; + +import from SCCP_Types all; +import from SCCPasp_Types all; +import from SCCP_Emulation all; + +/* +import from MobileL3_Types all; +import from MobileL3_CommonIE_Types all; +import from L3_Templates all; + +import from BSSAP_Types all; +import from BSSMAP_Templates all; +*/ +import from BSSMAP_Emulation all; + +import from MSC_ConnectionHandler all; + +type component MSC_CT { + /* component references */ + var IPA_Emulation_CT vc_IPA; + var SCCP_CT vc_SCCP; + var BSSMAP_Emulation_CT vc_BSSMAP; + /* test port to SCCP emulation */ + port SCCPasp_PT SCCP; +} + +function main(charstring local_ip, PortNumber local_port, + MSC_SCCP_MTP3_parameters sccp_pars, + SCCP_PAR_Address sccp_addr_own) runs on MSC_CT +{ + /* create components */ + vc_IPA := IPA_Emulation_CT.create; + vc_SCCP := SCCP_CT.create; + vc_BSSMAP := BSSMAP_Emulation_CT.create; + + map(vc_IPA:IPA_PORT, system:IPA_CODEC_PT); + + /* connect MTP3 service provider (IPA) to lower side of SCCP */ + connect(vc_IPA:MTP3_SP_PORT, vc_SCCP:MTP3_SCCP_PORT); + + /* connect BSSNAP dispatcher to upper side of SCCP */ + connect(vc_BSSMAP:SCCP, vc_SCCP:SCCP_SP_PORT); + + vc_IPA.start(IPA_Emulation.main_server(local_ip, local_port)); + vc_SCCP.start(SCCPStart(sccp_pars)); + vc_BSSMAP.start(BSSMAP_Emulation.main(MSC_BssmapOps)); + + /* wait until termination of respective components */ + vc_IPA.done; + vc_BSSMAP.done; + vc_SCCP.done; +} + +} diff --git a/ipa/gen_links.sh b/ipa/gen_links.sh index d9bc7a4f7..be11ec053 100755 --- a/ipa/gen_links.sh +++ b/ipa/gen_links.sh @@ -47,5 +47,5 @@ gen_links $DIR $FILES DIR=../library -FILES="General_Types.ttcn Osmocom_Types.ttcn IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc L3_Templates.ttcn BSSMAP_Templates.ttcn" +FILES="General_Types.ttcn Osmocom_Types.ttcn IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcn L3_Templates.ttcn BSSMAP_Templates.ttcn BSSMAP_Emulation.ttcn" gen_links $DIR $FILES diff --git a/library/BSSMAP_Emulation.ttcn b/library/BSSMAP_Emulation.ttcn index bcc0e1128..9e4d5c3e8 100644 --- a/library/BSSMAP_Emulation.ttcn +++ b/library/BSSMAP_Emulation.ttcn @@ -1,5 +1,6 @@ module BSSMAP_Emulation { +import from SCCP_Emulation all; import from SCCPasp_Types all; import from BSSAP_Types all; import from BSSMAP_Templates all; @@ -20,10 +21,15 @@ type enumerated BSSAP_Conn_Prim { MSC_CONN_PRIM_DISC_REQ } +type record BSSAP_Conn_Req { + SCCP_PAR_Address addr_peer, + SCCP_PAR_Address addr_own, + PDU_BSSAP bssap +} + /* port between individual per-connection components and this dispatcher */ type port BSSAP_Conn_PT message { - inout PDU_BSSAP; - inout BSSAP_Conn_Prim; + inout PDU_BSSAP, BSSAP_Conn_Prim, BSSAP_Conn_Req; } with { extension "internal" }; @@ -44,6 +50,27 @@ type component BSSMAP_Emulation_CT { var ConnectionData ConnectionTable[16]; }; +private function f_conn_id_known(integer sccp_conn_id) +runs on BSSMAP_Emulation_CT return boolean { + var integer i; + for (i := 0; i < sizeof(ConnectionTable); i := i+1) { + if (ConnectionTable[i].sccp_conn_id == sccp_conn_id){ + return true; + } + } + return false; +} + +private function f_comp_known(BSSAP_ConnHdlr client) +runs on BSSMAP_Emulation_CT return boolean { + var integer i; + for (i := 0; i < sizeof(ConnectionTable); i := i+1) { + if (ConnectionTable[i].comp_ref == client) { + return true; + } + } + return false; +} /* resolve component reference by connection ID */ private function f_comp_by_conn_id(integer sccp_conn_id) @@ -70,6 +97,17 @@ runs on BSSMAP_Emulation_CT return integer { self.stop; } +private function f_gen_conn_id() +runs on BSSMAP_Emulation_CT return integer { + var integer conn_id; + + do { + conn_id := float2int(rnd()*SCCP_Emulation.tsp_max_ConnectionId); + } while (f_conn_id_known(conn_id) == true); + + return conn_id; +} + private function f_conn_table_init() runs on BSSMAP_Emulation_CT { for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) { @@ -84,6 +122,7 @@ runs on BSSMAP_Emulation_CT { if (ConnectionTable[i].sccp_conn_id == -1) { ConnectionTable[i].comp_ref := comp_ref; ConnectionTable[i].sccp_conn_id := sccp_conn_id; + log("Added conn table entry ", i, comp_ref, sccp_conn_id); return; } } @@ -95,6 +134,8 @@ private function f_conn_table_del(integer sccp_conn_id) runs on BSSMAP_Emulation_CT { for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) { if (ConnectionTable[i].sccp_conn_id == sccp_conn_id) { + log("Deleted conn table entry ", i, + ConnectionTable[i].comp_ref, sccp_conn_id); ConnectionTable[i].sccp_conn_id := -1; ConnectionTable[i].comp_ref := null; } @@ -135,8 +176,10 @@ function main(BssmapOps ops) runs on BSSMAP_Emulation_CT { while (true) { var ASP_SCCP_N_UNITDATA_ind ud_ind; var ASP_SCCP_N_CONNECT_ind conn_ind; + var ASP_SCCP_N_CONNECT_cfm conn_cfm; var ASP_SCCP_N_DATA_ind data_ind; var ASP_SCCP_N_DISCONNECT_ind disc_ind; + var BSSAP_Conn_Req creq; var BSSAP_ConnHdlr vc_conn; var PDU_BSSAP bssap; @@ -183,6 +226,12 @@ function main(BssmapOps ops) runs on BSSMAP_Emulation_CT { /* TOOD: return confirm to other side? */ } + /* SCCP -> Client: connection confirm for outbound connection */ + [] SCCP.receive(ASP_SCCP_N_CONNECT_cfm:?) -> value conn_cfm { + /* handle user payload */ + f_handle_userData(vc_conn, conn_cfm.userData); + } + /* Disconnect request client -> SCCP */ [] CLIENT.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_REQ) -> sender vc_conn { var integer conn_id := f_conn_id_by_comp(vc_conn); @@ -191,9 +240,31 @@ function main(BssmapOps ops) runs on BSSMAP_Emulation_CT { } /* BSSAP from client -> SCCP */ + [] CLIENT.receive(BSSAP_Conn_Req:?) -> value creq sender vc_conn { + var integer conn_id; + /* encode + send to dispatcher */ + var octetstring userdata := enc_PDU_BSSAP(creq.bssap); + + if (f_comp_known(vc_conn) == false) { + /* unknown client, create new connection */ + conn_id := f_gen_conn_id(); + + /* store mapping between client components and SCCP connectionId */ + f_conn_table_add(vc_conn, conn_id); + + SCCP.send(t_ASP_N_CONNECT_req(creq.addr_peer, creq.addr_own, omit, omit, + userdata, conn_id, omit)); + } else { + /* known client, send via existing connection */ + conn_id := f_conn_id_by_comp(vc_conn); + SCCP.send(t_ASP_N_DATA_req(userdata, conn_id, omit)); + } + + } + [] CLIENT.receive(PDU_BSSAP:?) -> value bssap sender vc_conn { var integer conn_id := f_conn_id_by_comp(vc_conn); - /* encode + send to dispatcher */ + /* encode + send it to dispatcher */ var octetstring userdata := enc_PDU_BSSAP(bssap); SCCP.send(t_ASP_N_DATA_req(userdata, conn_id, omit)); } diff --git a/library/BSSMAP_Templates.ttcn b/library/BSSMAP_Templates.ttcn index b030072ee..274f42e5e 100644 --- a/library/BSSMAP_Templates.ttcn +++ b/library/BSSMAP_Templates.ttcn @@ -11,7 +11,9 @@ template PDU_BSSAP ts_BSSAP_BSSMAP := { spare := '0000000'B, dlci := omit, lengthIndicator := 0, /* overwritten by codec */ - pdu := ? + pdu := { + bssmap := ? + } } template PDU_BSSAP tr_BSSAP_BSSMAP := { @@ -24,6 +26,27 @@ template PDU_BSSAP tr_BSSAP_BSSMAP := { } } +template PDU_BSSAP ts_BSSAP_DTAP := { + discriminator := '1'B, + spare := '0000000'B, + dlci := omit, + lengthIndicator := 0, /* overwritten by codec */ + pdu := { + dtap := ? + } +} + +template PDU_BSSAP tr_BSSAP_DTAP := { + discriminator := '1'B, + spare := '0000000'B, + dlci := omit, + lengthIndicator := ?, + pdu := { + dtap := ? + } +} + + template (value) BSSMAP_IE_Cause ts_BSSMAP_IE_Cause(BssmapCause val) := { elementIdentifier := '04'O, lengthIndicator := 0, @@ -238,4 +261,119 @@ modifies ts_BSSAP_BSSMAP := { } } +template PDU_BSSAP tr_BSSMAP_AssignmentCmd modifies tr_BSSAP_BSSMAP := { + pdu := { + bssmap := { + assignmentRequest := { + messageType :='01'O, /* overwritten */ + channelType := ?, + layer3HeaderInfo := *, + priority := *, + circuitIdentityCode := ?, + downLinkDTX_Flag := *, + interferenceBandToBeUsed := *, + classmarkInformationType2 := *, + groupCallReference := *, + talkerFlag := *, + configurationEvolutionIndication := *, + lsaAccesControlSuppression := *, + serviceHandover := *, + encryptionInformation := *, + talkerPriority := *, + aoIPTransportLayer := *, + codecList := *, + callIdentifier := *, + kC128 := *, + globalCallReference := *, + lCLS_Configuration := *, + lCLS_ConnectionStatusControl := *, + lCLS_CorrelationNotNeeded := * + } + } + } +} + +template (value) PDU_BSSAP ts_BSSMAP_AssignmentComplete(BSSMAP_IE_CircuitIdentityCode cic) +modifies ts_BSSAP_BSSMAP := { + pdu := { + bssmap := { + assignmentComplete := { + messageType :='02'O, /* overwritten */ + circuitIdentityCode := cic, + cellIdentifier := omit, + chosenChannel := omit, + chosenEncryptionAlgorithm := omit, + circuitPool := omit, + speechVersion := omit, + lSAIdentifier := omit, + talkerPriority := omit, + aoIPTransportLayer := omit, + speechCodec := omit, + codecList := omit, + lCLS_BSS_Status := omit + } + } + } +} + +template PDU_BSSAP tr_BSSMAP_AssignmentComplete modifies tr_BSSAP_BSSMAP := { + pdu := { + bssmap := { + assignmentComplete := { + messageType := '02'O, /* overwritten */ + circuitIdentityCode := ?, + cellIdentifier := *, + chosenChannel := *, + chosenEncryptionAlgorithm := *, + circuitPool := *, + speechVersion := *, + lSAIdentifier := *, + talkerPriority := *, + aoIPTransportLayer := *, + speechCodec := *, + codecList := *, + lCLS_BSS_Status := * + } + } + } +} + +template (value) PDU_BSSAP ts_BSSMAP_ClearCommand(BssmapCause cause) +modifies ts_BSSAP_BSSMAP := { + pdu := { + bssmap := { + clearCommand := { + messageType := '20'O, /* overwritten */ + layer3HeaderInfo := omit, + cause := ts_BSSMAP_IE_Cause(cause), + cSFB_Indication := omit + } + } + } +} + +template PDU_BSSAP tr_BSSMAP_ClearCommand modifies tr_BSSAP_BSSMAP := { + pdu := { + bssmap := { + clearCommand := { + messageType := '20'O, /* overwritten */ + layer3HeaderInfo := *, + cause := ?, + cSFB_Indication := * + } + } + } +} + +template (value) PDU_BSSAP ts_BSSMAP_ClearComplete +modifies ts_BSSAP_BSSMAP := { + pdu := { + bssmap := { + clearComplete := { + messageType := '21'O /* overwritten */ + } + } + } +} + } diff --git a/library/IPA_Emulation.ttcn b/library/IPA_Emulation.ttcn index 4d21bb466..ed5111032 100644 --- a/library/IPA_Emulation.ttcn +++ b/library/IPA_Emulation.ttcn @@ -12,6 +12,11 @@ modulepar { } */ +type enumerated IpaMode { + IPA_MODE_CLIENT, + IPA_MODE_SERVER +} + type record ASP_IPA_Unitdata { IpaStreamId streamId, octetstring payload @@ -31,6 +36,8 @@ type component IPA_Emulation_CT { var boolean g_initialized := false; var ConnectionId g_ipa_conn_id := -1; + + var IpaMode g_mode; } function f_connect(charstring remote_host, PortNumber remote_port, @@ -41,6 +48,13 @@ function f_connect(charstring remote_host, PortNumber remote_port, g_ipa_conn_id := res.connId; } +function f_bind(charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT { + var Result res; + res := IPA_CodecPort_CtrlFunct.f_IPL4_listen(IPA_PORT, + local_host, local_port, { tcp:={} }); + g_ipa_conn_id := res.connId; +} + template ASP_MTP3_TRANSFERind ts_MTP3_XFER_ind(integer opc, octetstring data) := { sio := { '10'B, '00'B, '0011'B }, opc := opc, @@ -107,6 +121,15 @@ template PDU_IPA_CCM ts_IPA_ACK := { u := omit } +template PDU_IPA_CCM ts_IPA_ID_GET := { + msg_type := IPAC_MSGT_ID_GET, + u := { + get := { + { 1, IPAC_IDTAG_UNITNAME } + } + } +} + /* receive IPA CCM message */ private function f_ccm_rx(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT { select (ccm.msg_type) { @@ -142,12 +165,24 @@ private function f_from_asp(ConnectionId connId, ASP_IPA_Unitdata ipa_tx) return return ret; } -function ScanEvents() runs on IPA_Emulation_CT { +function main_client(charstring remote_host, PortNumber remote_port, + charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT { + g_mode := IPA_MODE_CLIENT; + f_connect(remote_host, remote_port, local_host, local_port); + ScanEvents(); +} + +function main_server(charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT { + g_mode := IPA_MODE_SERVER; + f_bind(local_host, local_port); + ScanEvents(); +} + +private function ScanEvents() runs on IPA_Emulation_CT { var IPA_RecvFrom ipa_rx; var ASP_IPA_Unitdata ipa_ud; var ASP_MTP3_TRANSFERreq mtp_req; - - f_connect("127.0.0.1", 5000, "127.0.0.1", 49999); + var ASP_Event asp_evt; while (true) { alt { @@ -170,6 +205,21 @@ function ScanEvents() runs on IPA_Emulation_CT { } } + /* server only */ + [] IPA_PORT.receive(ASP_Event:{connOpened:=?}) -> value asp_evt { + log("IPA: Connected"); + g_ipa_conn_id := asp_evt.connOpened.connId; + if (g_mode == IPA_MODE_SERVER) { + f_ccm_tx(valueof(ts_IPA_ID_GET)); + } + } + + [] IPA_PORT.receive(ASP_Event:{connClosed:=?}) -> value asp_evt { + log("IPA: Closed"); + g_ipa_conn_id := -1; + self.stop; + } + /* Received SCCP -> down into IPA */ [] MTP3_SP_PORT.receive(ASP_MTP3_TRANSFERreq: ?) -> value mtp_req { var IPA_Send ipa_tx := {