From 79feba5ed43f98b3be2a2e0b8f77ad69ec8c3c50 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 25 Nov 2017 02:32:50 +0100 Subject: rename 'ipa' directory to 'bsc-nat' --- bsc-nat/BSC_MS_ConnectionHandler.ttcn | 162 ++++++++++++++++++++++++++++++++++ bsc-nat/BSC_MS_Simulation.ttcn | 94 ++++++++++++++++++++ bsc-nat/IPA_Test.cfg | 29 ++++++ bsc-nat/IPA_Test.ttcn | 149 +++++++++++++++++++++++++++++++ bsc-nat/MGCP_Adapter.ttcn | 72 +++++++++++++++ bsc-nat/MSC_ConnectionHandler.ttcn | 154 ++++++++++++++++++++++++++++++++ bsc-nat/MSC_Simulation.ttcn | 78 ++++++++++++++++ bsc-nat/gen_links.sh | 59 +++++++++++++ bsc-nat/regen_makefile.sh | 11 +++ 9 files changed, 808 insertions(+) create mode 100644 bsc-nat/BSC_MS_ConnectionHandler.ttcn create mode 100644 bsc-nat/BSC_MS_Simulation.ttcn create mode 100644 bsc-nat/IPA_Test.cfg create mode 100644 bsc-nat/IPA_Test.ttcn create mode 100644 bsc-nat/MGCP_Adapter.ttcn create mode 100644 bsc-nat/MSC_ConnectionHandler.ttcn create mode 100755 bsc-nat/MSC_Simulation.ttcn create mode 100755 bsc-nat/gen_links.sh create mode 100755 bsc-nat/regen_makefile.sh (limited to 'bsc-nat') diff --git a/bsc-nat/BSC_MS_ConnectionHandler.ttcn b/bsc-nat/BSC_MS_ConnectionHandler.ttcn new file mode 100644 index 00000000..ee564013 --- /dev/null +++ b/bsc-nat/BSC_MS_ConnectionHandler.ttcn @@ -0,0 +1,162 @@ +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; + +import from MGCP_Types all; +import from MGCP_Templates all; +import from SDP_Types 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; + var MgcpConnectionId g_mgcp_conn_id; + var SDP_Message g_sdp; + var BSC_State g_state; +} + +/* 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, charstring id) +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; +} + +type enumerated BSC_State { + BSC_STATE_NONE, + BSC_STATE_WAIT_ASS_REQ, + BSC_STATE_WAIT_CRCX, + BSC_STATE_WAIT_MDCX, + BSC_STATE_WAIT_CLEAR_CMD, + BSC_STATE_WAIT_DLCX, + BSC_STATE_WAIT_DISC_IND +} + +/* 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; + var MgcpCommand mgcp_cmd; + var MgcpResponse mgcp_resp; + + log("Starting main of BSC_MS_ConnHdlr"); + + g_mgcp_conn_id := f_mgcp_alloc_conn_id(); + + /* 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 + } + g_state := BSC_STATE_WAIT_ASS_REQ; + BSSAP.send(creq); + + while (true) { + alt { + /* new SCCP-level connection indication from BSC */ + [g_state == BSC_STATE_WAIT_ASS_REQ] BSSAP.receive(tr_BSSMAP_AssignmentReq) -> value bssap { + /* FIXME: Read CIC */ + /* respond with ASSIGNMENT COMPL */ + g_state := BSC_STATE_WAIT_CRCX; + BSSAP.send(ts_BSSMAP_AssignmentComplete(bssap.pdu.bssmap.assignmentRequest.circuitIdentityCode)); + } + + /* CRCX -> OK */ + [g_state == BSC_STATE_WAIT_CRCX] BSSAP.receive(tr_CRCX) -> value mgcp_cmd { + /* FIXME: proper SDP parameters */ + g_sdp := valueof(ts_SDP("127.0.0.1", "127.0.0.1", "foo", "21", 1000, { "98" }, + { valueof(ts_SDP_rtpmap(98, "AMR/8000")), + valueof(ts_SDP_ptime(20)) })); + /* respond with CRCX_ACK */ + g_state := BSC_STATE_WAIT_MDCX; + BSSAP.send(ts_CRCX_ACK(mgcp_cmd.line.trans_id, g_mgcp_conn_id, g_sdp)); + } + + /* MDCX -> OK */ + [g_state == BSC_STATE_WAIT_MDCX] BSSAP.receive(tr_MDCX) -> value mgcp_cmd { + /* FIXME: verify if local part of endpoint name matches CIC */ + /* respond with CRCX_ACK */ + g_state := BSC_STATE_WAIT_CLEAR_CMD; + BSSAP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, g_mgcp_conn_id, g_sdp)); + } + + /* CLEAR COMMAND from MSC; respond with CLEAR COMPLETE) */ + [g_state == BSC_STATE_WAIT_CLEAR_CMD] BSSAP.receive(tr_BSSMAP_ClearCommand) -> value bssap { + g_state := BSC_STATE_WAIT_DLCX; + BSSAP.send(ts_BSSMAP_ClearComplete); + } + + /* DLCX -> OK */ + [g_state == BSC_STATE_WAIT_DLCX] BSSAP.receive(tr_DLCX) -> value mgcp_cmd { + /* FIXME: verify if local part of endpoint name matches CIC */ + g_state := BSC_STATE_WAIT_DISC_IND; + BSSAP.send(ts_DLCX_ACK(mgcp_cmd.line.trans_id, g_mgcp_conn_id)); + } + + [] BSSAP.receive(tr_BSSAP_DTAP) -> value bssap { + /* FIXME: verify if local part of endpoint name matches CIC */ + var PDU_ML3_MS_NW l3 := dec_PDU_ML3_MS_NW(bssap.pdu.dtap); + log("Unhandled DTAP ", l3); + } + + [g_state == BSC_STATE_WAIT_DISC_IND] BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND) { + setverdict(pass); + self.stop; + } + + /* disconnect in invalid state */ + [] BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND) { + setverdict(fail); + self.stop; + } + + + [] BSSAP.receive(PDU_BSSAP:?) -> value bssap { + log("Received unhandled SCCP-CO: ", bssap); + } + } + } +} + +} diff --git a/bsc-nat/BSC_MS_Simulation.ttcn b/bsc-nat/BSC_MS_Simulation.ttcn new file mode 100644 index 00000000..eab7fe9d --- /dev/null +++ b/bsc-nat/BSC_MS_Simulation.ttcn @@ -0,0 +1,94 @@ +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; + + var charstring g_bsc_num_str; +} + +modulepar { + integer mp_num_iterations := 10; +} + +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, charstring id) runs on BSC_CT +{ + var integer i := 0; + timer T := 1.0; + + g_sccp_addr_own := sccp_addr_own; + g_sccp_addr_remote := sccp_addr_remote; + + /* create components for IPA/SCCP/BSS[M]AP stack */ + vc_IPA := IPA_Emulation_CT.create(id & "-IPA"); + vc_SCCP := SCCP_CT.create(id & "-SCCP"); + vc_BSSMAP := BSSMAP_Emulation_CT.create(id & "-BSSMAP"); + + 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 BSSMAP dispatcher to upper side of SCCP */ + connect(vc_BSSMAP:SCCP, vc_SCCP:SCCP_SP_PORT); + + /* connect BSSMAP dispatcher to IPA_Emulation MGCP */ + connect(vc_BSSMAP:MGCP, vc_IPA:IPA_MGCP_PORT); + + /* start components */ + 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, id)); + + /* Initial delay to wait for IPA connection establishment */ + T.start(2.0); + T.timeout; + + for (i := 0; i < mp_num_iterations; i := i+1) { + f_start_BSC_MS(id & "-MS-" & int2str(i)); + } + + /* explicitly stop all components that we started above */ + vc_IPA.stop; + vc_BSSMAP.stop; + vc_SCCP.stop; +} + +function f_start_BSC_MS(charstring id) runs on BSC_CT { + var BSC_MS_ConnHdlr vc_conn; + + /* start new component */ + vc_conn := BSC_MS_ConnHdlr.create(id); + /* 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)); + /* blocking wait until component terminates. If you want to start MSs in parallel, + * you have to remove this statement here */ + vc_conn.done; +} + +} diff --git a/bsc-nat/IPA_Test.cfg b/bsc-nat/IPA_Test.cfg new file mode 100644 index 00000000..3a341023 --- /dev/null +++ b/bsc-nat/IPA_Test.cfg @@ -0,0 +1,29 @@ +[LOGGING] +#FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC; +#ConsoleMask := ERROR | WARNING | TESTCASE | TTCN_MATCHING | DEBUG_ENCDEC +FileMask := LOG_ALL | TTCN_MATCHING; + +[TESTPORT_PARAMETERS] +#*.*.udpReuseAddress := "yes"; + +[MODULE_PARAMETERS] +#mp_bsc_port := 49999; +#mp_bsc_ip := "127.0.0.1"; +#mp_msc_port := 5100; +#mp_msc_ip := "127.0.0.1"; +#mp_nat_port := 5000; +#mp_nat_ip := "127.0.0.1"; + +#mp_ipa_mgcp_uses_osmo_ext := true; + +#mp_mgcp_uses_udp := true; +#mp_callagent_ip := "127.0.0.1"; +#mp_callagent_udp_port := 2727; +#mp_mgw_ip := "127.0.0.1"; +#mp_mgw_udp_port := 2427; + +[MAIN_CONTROLLER] + +[EXECUTE] +#MGCP_Test.TC_selftest +IPA_Test.TC_recv_dump diff --git a/bsc-nat/IPA_Test.ttcn b/bsc-nat/IPA_Test.ttcn new file mode 100644 index 00000000..fbff84ab --- /dev/null +++ b/bsc-nat/IPA_Test.ttcn @@ -0,0 +1,149 @@ +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 MSC_Simulation all; +import from BSC_MS_Simulation 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 { + var MscState msc[NUM_MSC]; + var BscState bsc[NUM_BSC]; + + var boolean g_initialized := false; + var octetstring g_sio := '83'O; +} + +modulepar { + 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"; + + PortNumber mp_nat_port := 5000; + charstring mp_nat_ip := "127.0.0.1"; + + charstring mp_sccp_service_type := "mtp3_itu"; + + integer mp_bsc_pc := 196; + integer mp_bsc_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 */ +template (value) SCCP_PAR_Address ts_SccpAddr_PC_SSN(integer pc, integer ssn) := { + addressIndicator := { + pointCodeIndic := '1'B, + ssnIndicator := '1'B, + globalTitleIndic := '0000'B, + routingIndicator := '1'B + }, + signPointCode := SCCP_SPC_int2bit(pc, mp_sccp_service_type, '83'O), + //signPointCode := SCCP_SPC_int2bit(pc, mp_sccp_service_type, g_sio), + subsystemNumber := ssn, + globalTitle := omit +} + +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) +} + +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 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)); +} + +function f_init() runs on test_CT { + var integer i; + var charstring id; + + 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; + id := "MSC" & int2str(i); + msc[i].MSC.start(MSC_Simulation.main(mp_msc_ip, mp_msc_port + i, msc[i].sccp_pars, msc[i].sccp_addr_own, id)); + } + + 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; + id := "BSC" & int2str(i); + bsc[i].BSC.start(BSC_MS_Simulation.main(mp_nat_ip, mp_nat_port, mp_bsc_ip, mp_bsc_port+i, + bsc[i].sccp_pars, bsc[i].sccp_addr_own, + bsc[i].sccp_addr_peer, id)); + } + +} + +testcase TC_recv_dump() runs on test_CT { + var integer i; + timer T := 30.0; + + f_init(); + + alt { + /* wait for BSC to stop. The idea is that the BSC components terminate first */ + [] bsc[0].BSC.done { } + [] T.timeout { setverdict(fail); } + } + + all component.stop; + /* terminate the MSCs */ + for (i := 0; i < NUM_MSC; i := i+1) { + msc[i].MSC.stop; + } +} + +control { + execute( TC_recv_dump() ); +} + +} diff --git a/bsc-nat/MGCP_Adapter.ttcn b/bsc-nat/MGCP_Adapter.ttcn new file mode 100644 index 00000000..1351997c --- /dev/null +++ b/bsc-nat/MGCP_Adapter.ttcn @@ -0,0 +1,72 @@ +module MGCP_Adapter { + +import from IPL4asp_Types all; + +import from MGCP_Types all; +import from MGCP_CodecPort all; +import from MGCP_CodecPort_CtrlFunct all; + +import from IPA_Emulation all; + + +type component MGCP_Adapter_CT { + /* MGCP Codec Port for MGCP-over-UDP */ + port MGCP_CODEC_PT MGCP_UDP; + port IPA_MGCP_PT MGCP; + var integer g_mgcp_conn_id := -1; +} + +modulepar { + charstring mp_callagent_ip := "127.0.0.1"; + PortNumber mp_callagent_udp_port := 2727; + charstring mp_mgw_ip := "127.0.0.1"; + PortNumber mp_mgw_udp_port := 2427; +} + +/* build a receive template for receiving a MGCP message. You + * pass the MGCP response template in, and it will generate an + * MGCP_RecvFrom template that can match the primitives arriving on the + * MGCP_CodecPort */ +function tr_MGCP_RecvFrom_R(template MgcpResponse resp) +runs on MGCP_Adapter_CT return template MGCP_RecvFrom { + var template MGCP_RecvFrom mrf := { + connId := g_mgcp_conn_id, + remName := mp_mgw_ip, + remPort := mp_mgw_udp_port, + locName := mp_callagent_ip, + locPort := mp_callagent_udp_port, + msg := { response := resp } + } + return mrf; +} + + +function main() runs on MGCP_Adapter_CT { + var Result res; + map(self:MGCP_UDP, system:MGCP_CODEC_PT); + res := MGCP_CodecPort_CtrlFunct.f_IPL4_connect(MGCP_UDP, mp_mgw_ip, mp_mgw_udp_port, + mp_callagent_ip, mp_callagent_udp_port, + 0, { udp:={} }); + g_mgcp_conn_id := res.connId; + + while (true) { + var MgcpCommand mgcp_cmd; + var MGCP_RecvFrom mrf; + + alt { + /* From BSC/MGW via UDP up to MSC / Call Agent */ + [] MGCP_UDP.receive(tr_MGCP_RecvFrom_R(?)) -> value mrf { + MGCP.send(mrf.msg.response); + } + + /* From MSC / Call Agent down to BSC/MGW */ + [] MGCP.receive(MgcpCommand:?) -> value mgcp_cmd { + var MgcpMessage msg := { command := mgcp_cmd }; + MGCP_UDP.send(t_MGCP_Send(g_mgcp_conn_id, msg)); + } + + } + } +} + +} diff --git a/bsc-nat/MSC_ConnectionHandler.ttcn b/bsc-nat/MSC_ConnectionHandler.ttcn new file mode 100644 index 00000000..6a9a57f9 --- /dev/null +++ b/bsc-nat/MSC_ConnectionHandler.ttcn @@ -0,0 +1,154 @@ +module MSC_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 MGCP_Types all; +import from MGCP_Templates all; +import from SDP_Types 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 MSC_ConnHdlr extends BSSAP_ConnHdlr { + /* SCCP Connecction Identifier for the underlying SCCP connection */ + var integer g_sccp_conn_id; + + var MSC_State g_state := MSC_STATE_NONE; + var MgcpEndpoint g_ep_name; + var MgcpCallId g_call_id; + var MgcpConnectionId g_mgcp_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, charstring id) +runs on BSSMAP_Emulation_CT return BSSAP_ConnHdlr { + var MSC_ConnHdlr vc_conn; + /* Create a new BSSAP_ConnHdlr component */ + vc_conn := MSC_ConnHdlr.create(g_bssmap_id & "-Conn-" & int2str(conn_ind.connectionId)); + /* connect it to the port */ + connect(vc_conn:BSSAP, self:CLIENT); + /* start it */ + vc_conn.start(MSC_ConnectionHandler.main(conn_ind.connectionId, g_next_e1_ts)); + /* increment next E1 timeslot */ + g_next_e1_ts := g_next_e1_ts + 1; + return vc_conn; +} + +/* 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 MSC_BssmapOps := { + create_cb := refers(CreateCallback), + unitdata_cb := refers(UnitdataCallback) +} + +type enumerated MSC_State { + MSC_STATE_NONE, + MSC_STATE_WAIT_ASS_COMPL, + MSC_STATE_WAIT_CRCX_ACK, + MSC_STATE_WAIT_MDCX_ACK, + MSC_STATE_WAIT_CLEAR_COMPL, + MSC_STATE_WAIT_DLCX_ACK +} + +/* main function processing various incoming events */ +function main(integer connection_id, integer e1_timeslot) runs on MSC_ConnHdlr { + var MgcpResponse mgcp_rsp; + timer T := 5.0; + + g_sccp_conn_id := connection_id; + g_call_id := f_mgcp_alloc_call_id(); + g_ep_name := hex2str(int2hex(e1_timeslot, 1)) & "@mgw"; + + /* we just accepted an incoming SCCP connection, start guard timer */ + T.start; + + while (true) { + var PDU_BSSAP bssap; + alt { + /* new SCCP-level connection indication from BSC */ + [g_state == MSC_STATE_NONE] BSSAP.receive(tr_BSSMAP_ComplL3) -> value bssap { + /* respond with ASSIGNMENT CMD */ + g_state := MSC_STATE_WAIT_ASS_COMPL; + BSSAP.send(ts_BSSMAP_AssignmentReq(0, e1_timeslot)); + } + [g_state == MSC_STATE_WAIT_ASS_COMPL] BSSAP.receive(tr_BSSMAP_AssignmentComplete) { + /* FIXME: Send MGCP CRCX */ + g_state := MSC_STATE_WAIT_CRCX_ACK; + var MgcpTransId trans_id := f_mgcp_alloc_tid(); + //template SDP_Message sdp := omit; + BSSAP.send(ts_CRCX(trans_id, g_ep_name, "recvonly", g_call_id)); //, sdp)); + } + /* + [] BSSAP.receive(tr_BSSMAP_AssignmentFail) { + } + */ + + /* receive CRCX ACK: transmit MDCX */ + [g_state == MSC_STATE_WAIT_CRCX_ACK] BSSAP.receive(tr_CRCX_ACK) -> value mgcp_rsp { + /* extract connection ID */ + g_mgcp_conn_id := f_MgcpResp_extract_conn_id(mgcp_rsp); + g_state := MSC_STATE_WAIT_MDCX_ACK; + var MgcpTransId trans_id := f_mgcp_alloc_tid(); + BSSAP.send(ts_MDCX(trans_id, g_ep_name, "sendrecv", g_call_id, g_mgcp_conn_id)); + } + + /* receive MDCX ACK: wait + transmit CLEAR COMMAND */ + [g_state == MSC_STATE_WAIT_MDCX_ACK] BSSAP.receive(tr_CRCX_ACK) -> value mgcp_rsp { + g_state := MSC_STATE_WAIT_CLEAR_COMPL + BSSAP.send(ts_BSSMAP_ClearCommand(9)); /* Cause: call control */ + } + + /* CLEAR COMPLETE from BSS (response to CLEAR COMMAND) */ + [g_state == MSC_STATE_WAIT_CLEAR_COMPL] BSSAP.receive(tr_BSSMAP_ClearComplete) { + /* send DLCX */ + g_state := MSC_STATE_WAIT_DLCX_ACK; + var MgcpTransId trans_id := f_mgcp_alloc_tid(); + BSSAP.send(ts_DLCX(trans_id, g_ep_name, g_call_id)); + } + + [g_state == MSC_STATE_WAIT_DLCX_ACK] BSSAP.receive(tr_DLCX_ACK) { + BSSAP.send(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_REQ); + setverdict(pass); + self.stop; + } + + /* TODO: CLEAR REQUEST from BSS */ + + [] BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND) { + setverdict(fail); + self.stop; + } + + [] BSSAP.receive(PDU_BSSAP:?) -> value bssap { + log("Received unhandled SCCP-CO: ", bssap); + } + + /* Guard timer has expired, close connection */ + [] T.timeout { + BSSAP.send(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_REQ); + setverdict(inconc); + self.stop; + } + + } + } +} + +} diff --git a/bsc-nat/MSC_Simulation.ttcn b/bsc-nat/MSC_Simulation.ttcn new file mode 100755 index 00000000..f9fb0d42 --- /dev/null +++ b/bsc-nat/MSC_Simulation.ttcn @@ -0,0 +1,78 @@ +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 MGCP_Adapter 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; + var MGCP_Adapter_CT vc_MGCP_UDP; + /* test port to SCCP emulation */ + port SCCPasp_PT SCCP; +} + +modulepar { + boolean mp_mgcp_uses_udp := false; +} + +function main(charstring local_ip, PortNumber local_port, + MSC_SCCP_MTP3_parameters sccp_pars, + SCCP_PAR_Address sccp_addr_own, charstring id) runs on MSC_CT +{ + /* create components */ + vc_IPA := IPA_Emulation_CT.create(id & "-IPA"); + vc_SCCP := SCCP_CT.create(id & "-SCCP"); + vc_BSSMAP := BSSMAP_Emulation_CT.create(id & "-BSSMAP"); + + 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); + + if (mp_mgcp_uses_udp == false) { + /* connect BSSMAP dispatcher to IPA_Emulation MGCP */ + connect(vc_BSSMAP:MGCP, vc_IPA:IPA_MGCP_PORT); + } else { + vc_MGCP_UDP := MGCP_Adapter_CT.create(id & "-MGCP_UDP"); + connect(vc_BSSMAP:MGCP, vc_MGCP_UDP:MGCP); + vc_MGCP_UDP.start(MGCP_Adapter.main()); + } + + 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, id & "-BSSMAP")); + + /* wait until termination of respective components */ + vc_IPA.done; + vc_BSSMAP.done; + vc_SCCP.done; + if (mp_mgcp_uses_udp) { + vc_MGCP_UDP.done; + } +} + +} diff --git a/bsc-nat/gen_links.sh b/bsc-nat/gen_links.sh new file mode 100755 index 00000000..7be9a2d5 --- /dev/null +++ b/bsc-nat/gen_links.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +BASEDIR=~/projects/git + +gen_links() { + DIR=$1 + FILES=$* + for f in $FILES; do + echo "Linking $f" + ln -sf $DIR/$f $f + done +} + +#DIR=$BASEDIR/titan.TestPorts.UNIX_DOMAIN_SOCKETasp/src +#FILES="UD_PT.cc UD_PT.hh UD_PortType.ttcn UD_Types.ttcn" +#gen_links $DIR $FILES + +DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src +FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCConversion.hh TCCInterface.cc TCCInterface_ip.h SDP_EncDec.cc" +gen_links $DIR $FILES + +DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src +FILES="Socket_API_Definitions.ttcn" +gen_links $DIR $FILES + +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 + +# required by SCCP Emulation +DIR=../MTP3asp_CNL113337/src +FILES="MTP3asp_PortType.ttcn MTP3asp_Types.ttcn" +gen_links $DIR $FILES + +DIR=../SCCP_CNL113341/src +FILES="SCCP_Emulation.ttcn SCCP_EncDec.cc SCCP_Mapping.ttcnpp SCCP_Types.ttcn SCCPasp_Types.ttcn" +gen_links $DIR $FILES +ln -sf SCCP_Mapping.ttcnpp SCCP_Mapping.ttcn + +DIR=$BASEDIR/titan.ProtocolModules.BSSMAP_v11.2.0/src +FILES="BSSAP_Types.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" +gen_links $DIR $FILES + +DIR=$BASEDIR/titan.ProtocolModules.SDP/src +FILES="SDP_EncDec.cc SDP_Types.ttcn SDP_parse_.tab.c SDP_parse_.tab.h SDP_parse_parser.h SDP_parser.l +SDP_parser.y lex.SDP_parse_.c" +gen_links $DIR $FILES + +DIR=$BASEDIR/titan.ProtocolModules.RTP/src +FILES="RTP_EncDec.cc RTP_Types.ttcn" +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 IPA_Emulation.ttcn L3_Templates.ttcn BSSMAP_Templates.ttcn BSSMAP_Emulation.ttcn MGCP_Types.ttcn MGCP_Templates.ttcn MGCP_CodecPort.ttcn MGCP_CodecPort_CtrlFunct.ttcn MGCP_CodecPort_CtrlFunctDef.cc" +gen_links $DIR $FILES diff --git a/bsc-nat/regen_makefile.sh b/bsc-nat/regen_makefile.sh new file mode 100755 index 00000000..b6f6bb5f --- /dev/null +++ b/bsc-nat/regen_makefile.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +MAIN=IPA_Test.ttcn + +FILES="*.ttcn SCCP_EncDec.cc IPA_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc RTP_EncDec.cc SDP_EncDec.cc *.c MGCP_CodecPort_CtrlFunctDef.cc" + +ttcn3_makefilegen -l -f $MAIN $FILES +sed -i -e 's/# TTCN3_DIR = /TTCN3_DIR = \/usr/' Makefile +sed -i -e 's/LDFLAGS = /LDFLAGS = -L \/usr\/lib\/titan /' Makefile +#sed -i -e 's/TTCN3_LIB = ttcn3-parallel/TTCN3_LIB = ttcn3/' Makefile +sed -i -e 's/CPPFLAGS = -D$(PLATFORM) -I$(TTCN3_DIR)\/include/CPPFLAGS = -D$(PLATFORM) -I$(TTCN3_DIR)\/include -I\/usr\/include\/titan/' Makefile -- cgit v1.2.3