diff --git a/bsc-nat/BSCNAT_Tests.ttcn b/bsc-nat/BSCNAT_Tests.ttcn index fda065af5..47d894b57 100644 --- a/bsc-nat/BSCNAT_Tests.ttcn +++ b/bsc-nat/BSCNAT_Tests.ttcn @@ -16,6 +16,7 @@ import from Osmocom_Types all; import from IPL4asp_Types all; import from IPA_Emulation all; +import from RAN_Emulation all; import from MTP3asp_Types all; @@ -24,6 +25,7 @@ import from SCCPasp_Types all; import from SCCP_Emulation all; import from MSC_Simulation all; +import from MSC_ConnectionHandler all; import from BSC_MS_Simulation all; import from BSC_MS_ConnectionHandler all; @@ -136,7 +138,7 @@ function f_init_vty(charstring id := "foo") runs on test_CT { f_vty_transceive(BSCNATVTY, "enable"); } -function f_init(void_fn_bsc_ms fn_bsc_ms, boolean use_osmux) runs on test_CT { +function f_init(void_fn_bsc_ms fn_bsc_ms, BssmapCreateCallback cb_msc, boolean use_osmux) runs on test_CT { var integer i; var charstring id; @@ -147,7 +149,9 @@ function f_init(void_fn_bsc_ms fn_bsc_ms, boolean use_osmux) runs on test_CT { f_init_MscState(msc[i], mp_msc_pc +i, mp_bsc_pc, mp_msc_ssn, mp_bsc_ssn); id := "MSC" & int2str(i); msc[i].MSC := MSC_CT.create(id); - msc[i].MSC.start(MSC_Simulation.main(mp_msc_ip, mp_msc_port + i, msc[i].sccp_pars, msc[i].sccp_addr_own, id)); + msc[i].MSC.start(MSC_Simulation.main(mp_msc_ip, mp_msc_port + i, + msc[i].sccp_pars, msc[i].sccp_addr_own, + cb_msc, id)); } /* Wait for bsc_nat to attach to MSC. Before that all BSC connections will be dropped */ @@ -186,7 +190,9 @@ function f_wait_finish(timer T) runs on test_CT { function f_TC_recv_dump(boolean use_osmux := false) runs on test_CT { timer T := 30.0; - f_init(refers(bsc_ms_establish_fully), use_osmux); + f_init(refers(bsc_ms_establish_fully), + refers(CreateCallback_establish_fully), + use_osmux); f_wait_finish(T); } diff --git a/bsc-nat/MSC_ConnectionHandler.ttcn b/bsc-nat/MSC_ConnectionHandler.ttcn index c8cb00590..e4d381669 100644 --- a/bsc-nat/MSC_ConnectionHandler.ttcn +++ b/bsc-nat/MSC_ConnectionHandler.ttcn @@ -21,6 +21,8 @@ import from MGCP_Types all; import from MGCP_Templates all; import from SDP_Types all; +type function void_fn_msc(charstring id) runs on MSC_ConnHdlr; + /* this component represents a single subscriber connection at the MSC. * There is a 1:1 mapping between SCCP connections and RAN_ConnHdlr components. * We inherit all component variables, ports, functions, ... from RAN_ConnHdlr */ @@ -32,24 +34,38 @@ type component MSC_ConnHdlr extends RAN_ConnHdlr { var MgcpEndpoint g_ep_name; var MgcpCallId g_call_id; var MgcpConnectionId g_mgcp_conn_id; + var MSC_TestHdlrParams g_pars; } -/* Callback function from general BSSMAP_Emulation whenever a new incoming - * SCCP connection arrivces. Must create + start a new component */ -private function CreateCallback(BSSAP_N_CONNECT_ind conn_ind, charstring id) -runs on RAN_Emulation_CT return RAN_ConnHdlr { - var MSC_ConnHdlr vc_conn; - /* Create a new RAN_ConnHdlr component */ - vc_conn := MSC_ConnHdlr.create(g_ran_id & "-Conn-" & int2str(conn_ind.connectionId)); - /* connect it to the port */ +type record MSC_TestHdlrParams { + integer connection_id, + integer e1_timeslot +}; + +/* helper function to create and connect a MSC_ConnHdlr component */ +private function f_connect_handler(inout MSC_ConnHdlr vc_conn) runs on RAN_Emulation_CT { + /* connect client BSSAP port to BSSAP dispatcher */ 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; +} + +private function f_msc_start_handler(void_fn_msc fn, charstring id, template (omit) MSC_TestHdlrParams pars := omit) +runs on RAN_Emulation_CT return MSC_ConnHdlr { + var MSC_ConnHdlr vc_conn; + vc_conn := MSC_ConnHdlr.create(id); + f_connect_handler(vc_conn); + vc_conn.start(f_handler_init(fn, id, pars)); return vc_conn; } +/* first function inside ConnHdlr component; sets g_pars + starts function */ +private function f_handler_init(void_fn_msc fn, charstring id, template (omit) MSC_TestHdlrParams pars := omit) +runs on MSC_ConnHdlr { + if (isvalue(pars)) { + g_pars := valueof(pars); + } + fn.apply(id); +} + /* 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) @@ -63,8 +79,25 @@ runs on RAN_Emulation_CT return template PDU_BSSAP { return resp; } +/* Callback function from general BSSMAP_Emulation whenever a new incoming + * SCCP connection arrivces. Must create + start a new component */ +private function CreateCallback_generic(void_fn_msc fn, BSSAP_N_CONNECT_ind conn_ind, charstring id) +runs on RAN_Emulation_CT return RAN_ConnHdlr { + var MSC_ConnHdlr vc_conn; + var MSC_TestHdlrParams pars; + pars.connection_id := conn_ind.connectionId; + pars.e1_timeslot := g_next_e1_ts; + + /* Create a new RAN_ConnHdlr component */ + vc_conn := f_msc_start_handler(fn, g_ran_id & "-Conn-" & int2str(conn_ind.connectionId), pars); + + /* increment next E1 timeslot */ + g_next_e1_ts := g_next_e1_ts + 1; + return vc_conn; +} + const RanOps MSC_RanOps := { - create_cb := refers(CreateCallback), + create_cb := omit, unitdata_cb := refers(UnitdataCallback), decode_dtap := false, role_ms := false, @@ -84,14 +117,20 @@ type enumerated MSC_State { MSC_STATE_WAIT_DLCX_ACK } +/* Callback function from general BSSMAP_Emulation whenever a new incoming + * SCCP connection arrivces. Must create + start a new component */ +function CreateCallback_establish_fully(BSSAP_N_CONNECT_ind conn_ind, charstring id) +runs on RAN_Emulation_CT return RAN_ConnHdlr { + return CreateCallback_generic(refers(f_msc_establish_fully), conn_ind, id); +} /* main function processing various incoming events */ -function main(integer connection_id, integer e1_timeslot) runs on MSC_ConnHdlr { +function f_msc_establish_fully(charstring id) runs on MSC_ConnHdlr { var MgcpResponse mgcp_rsp; timer T := 5.0; - g_sccp_conn_id := connection_id; + g_sccp_conn_id := g_pars.connection_id; g_call_id := f_mgcp_alloc_call_id(); - g_ep_name := hex2str(int2hex(e1_timeslot, 1)) & "@mgw"; + g_ep_name := hex2str(int2hex(g_pars.e1_timeslot, 1)) & "@mgw"; /* we just accepted an incoming SCCP connection, start guard timer */ T.start; @@ -103,7 +142,7 @@ function main(integer connection_id, integer e1_timeslot) runs on MSC_ConnHdlr { [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(ts_BSSMAP_IE_CIC(0, e1_timeslot))); + BSSAP.send(ts_BSSMAP_AssignmentReq(ts_BSSMAP_IE_CIC(0, g_pars.e1_timeslot))); } [g_state == MSC_STATE_WAIT_ASS_COMPL] BSSAP.receive(tr_BSSMAP_AssignmentComplete(?,*)) { /* FIXME: Send MGCP CRCX */ diff --git a/bsc-nat/MSC_Simulation.ttcn b/bsc-nat/MSC_Simulation.ttcn index bc47f89f0..14229cc66 100755 --- a/bsc-nat/MSC_Simulation.ttcn +++ b/bsc-nat/MSC_Simulation.ttcn @@ -38,7 +38,8 @@ modulepar { 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 + SCCP_PAR_Address sccp_addr_own, + BssmapCreateCallback cb, charstring id) runs on MSC_CT { /* create components */ vc_IPA := IPA_Emulation_CT.create(id & "-IPA"); @@ -64,7 +65,10 @@ function main(charstring local_ip, PortNumber local_port, vc_IPA.start(IPA_Emulation.main_server(local_ip, local_port)); vc_SCCP.start(SCCPStart(sccp_pars)); - vc_BSSMAP.start(RAN_Emulation.main(MSC_ConnectionHandler.MSC_RanOps, id & "-BSSMAP")); + + var RanOps ranops := MSC_ConnectionHandler.MSC_RanOps; + ranops.create_cb := cb; + vc_BSSMAP.start(RAN_Emulation.main(ranops, id & "-BSSMAP")); /* wait until termination of respective components */ vc_IPA.done;