summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2019-06-17 14:07:02 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2019-06-18 17:13:51 +0200
commit2e5f63ba839ff88f1f8dee85a514815302c2d900 (patch)
tree7429bae9abd9139e1db895b64f610ae1d955c973
parent74a0b475474b1832707c207bd7e40f0027f2a343 (diff)
TODO: fix following: TC_ciph_mode_a5_3 TC_assignment_codec_fr_exhausted_req_fr TC_assignment_codec_hr_exhausted_req_hr TC_ho_out_of_this_bsc TC_ho_out_fail_no_ho_detect TC_ho_in_fail_msc_clears TC_ho_* Change-Id: I21ffcaa241e4fc0bd2c6563e21f1c8bdb4d14dd6
-rw-r--r--bsc/BSC_Tests.ttcn29
-rw-r--r--bsc/MSC_ConnectionHandler.ttcn235
-rw-r--r--library/BSSMAP_Templates.ttcn5
-rw-r--r--library/MGCP_CodecPort.ttcn36
-rw-r--r--library/MGCP_Emulation.ttcn55
-rw-r--r--msc/MSC_Tests.ttcn3
6 files changed, 284 insertions, 79 deletions
diff --git a/bsc/BSC_Tests.ttcn b/bsc/BSC_Tests.ttcn
index 976bc46..ec1be13 100644
--- a/bsc/BSC_Tests.ttcn
+++ b/bsc/BSC_Tests.ttcn
@@ -38,6 +38,7 @@ import from RSL_Emulation all;
import from MGCP_Emulation all;
import from MGCP_Templates all;
import from MGCP_Types all;
+import from MGCP_CodecPort all;
import from Osmocom_CTRL_Functions all;
import from Osmocom_CTRL_Types all;
@@ -294,7 +295,10 @@ function f_init_mgcp(charstring id) runs on test_CT {
callagent_ip := mp_bsc_ip,
callagent_udp_port := -1,
mgw_ip := mp_test_ip,
- mgw_udp_port := 2427
+ mgw_udp_port := 2427,
+ /* Enable it for SCCPlite, since we have 2 MGCP sockets towards MGW (UDP one +
+ the on with MGCP over IPA forwarded from MSC one) */
+ multi_conn_mode := (mp_bssap_cfg.transport == BSSAP_TRANSPORT_SCCPlite_SERVER)
};
vc_MGCP := MGCP_Emulation_CT.create(id);
@@ -1717,6 +1721,7 @@ private function f_connect_handler(inout MSC_ConnHdlr vc_conn) runs on test_CT {
}
connect(vc_conn:BSSAP, g_bssap.vc_RAN:CLIENT);
connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
+ connect(vc_conn:MGCP_MULTI, vc_MGCP:MGCP_CLIENT_MULTI);
}
function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
@@ -2890,18 +2895,32 @@ testcase TC_ho_int() runs on test_CT {
/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
private function f_expect_dlcx_conns(boolean exp_clear_cmpl := true) runs on MSC_ConnHdlr {
var MgcpCommand mgcp;
+ var template MgcpResponse mgcp_resp;
+ var MGCP_RecvFrom mrf;
+ var template MgcpMessage msg_resp;
+ var template MgcpMessage msg_dlcx := {
+ command := tr_DLCX()
+ }
- MGCP.receive(tr_DLCX()) -> value mgcp {
+ if (g_pars.aoip) {
+ MGCP.receive(tr_DLCX()) -> value mgcp {
log("Got first DLCX: ", mgcp);
MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
- };
+ };
- /* For SCCPLite, BSC doesn't handle the MSC-side */
- if (g_pars.aoip) {
MGCP.receive(tr_DLCX()) -> value mgcp {
log("Got second DLCX: ", mgcp);
MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
};
+ } else {
+ /* For SCCPLite, BSC doesn't handle the MSC-side */
+ MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
+ log("Got first DLCX: ", mrf.msg.command);
+ msg_resp := {
+ response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
+ }
+ MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
+ };
}
if (exp_clear_cmpl) {
diff --git a/bsc/MSC_ConnectionHandler.ttcn b/bsc/MSC_ConnectionHandler.ttcn
index c709794..8848512 100644
--- a/bsc/MSC_ConnectionHandler.ttcn
+++ b/bsc/MSC_ConnectionHandler.ttcn
@@ -15,6 +15,7 @@ import from Misc_Helpers all;
import from General_Types all;
import from Osmocom_Types all;
import from GSM_Types all;
+import from IPA_Emulation all;
import from SCCPasp_Types all;
import from BSSAP_Types all;
import from RAN_Emulation all;
@@ -23,6 +24,7 @@ import from BSSMAP_Templates all;
import from IPL4asp_Types all;
import from Native_Functions all;
+import from MGCP_CodecPort all;
import from MGCP_Types all;
import from MGCP_Templates all;
import from MGCP_Emulation all;
@@ -270,69 +272,126 @@ altstep as_Media_ipacc() runs on MSC_ConnHdlr {
}
+function f_rx_crcx(MgcpCommand mgcp_cmd)
+ runs on MSC_ConnHdlr return template MgcpResponse {
+ var MgcpOsmuxCID osmux_cid;
+ var SDP_Message sdp;
+ var integer cid := f_get_free_mgcp_conn();
+ if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard)) {
+ if (cid != 0) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "MGCP wildcard EP only works in first CRCX");
+ }
+ /* we keep the endpoint name allocated during MediaState_init */
+ } else {
+ /* Call Agent allocated endpoint, trust/use it always */
+ g_media.mgcp_ep := mgcp_cmd.line.ep;
+ }
+ if (isvalue(mgcp_cmd.sdp)) {
+ sdp := mgcp_cmd.sdp;
+ g_media.mgcp_conn[cid].peer.host := sdp.connection.conn_addr.addr;
+ g_media.mgcp_conn[cid].peer.port_nr := sdp.media_list[0].media_field.ports.port_number;
+ }
+ var MgcpConnState mgcp_conn := g_media.mgcp_conn[cid];
+ sdp := valueof(ts_SDP(mgcp_conn.mgw.host, mgcp_conn.mgw.host, "foo", "21",
+ mgcp_conn.mgw.port_nr, { int2str(mgcp_conn.rtp_pt) },
+ {valueof(ts_SDP_rtpmap(mgcp_conn.rtp_pt,
+ mgcp_conn.mime_type & "/" &
+ int2str(mgcp_conn.sample_rate))),
+ valueof(ts_SDP_ptime(mgcp_conn.ptime)) } ));
+ var template MgcpResponse mgcp_resp;
+ if (g_pars.use_osmux and f_MgcpCmd_contains_par(mgcp_cmd, "X-OSMUX")) {
+ osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
+ mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, mgcp_conn.conn_id, osmux_cid, sdp);
+ } else {
+ mgcp_resp := ts_CRCX_ACK(mgcp_cmd.line.trans_id, mgcp_conn.conn_id, sdp);
+ }
+ f_mgcp_par_append(mgcp_resp.params, ts_MgcpParSpecEP(g_media.mgcp_ep));
+ g_media.mgcp_conn[cid].crcx_seen := g_media.mgcp_conn[cid].crcx_seen + 1;
+ return mgcp_resp;
+}
+
+function f_rx_mdcx(MgcpCommand mgcp_cmd)
+ runs on MSC_ConnHdlr return template MgcpResponse {
+ var SDP_Message sdp;
+ var integer cid := f_get_mgcp_conn(f_MgcpCmd_extract_conn_id(mgcp_cmd));
+ if (isvalue(mgcp_cmd.sdp)) {
+ sdp := mgcp_cmd.sdp;
+ g_media.mgcp_conn[cid].peer.host := sdp.connection.conn_addr.addr;
+ g_media.mgcp_conn[cid].peer.port_nr := sdp.media_list[0].media_field.ports.port_number;
+ } else {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "MDCX has no [recognizable] SDP");
+ }
+ var MgcpConnState mgcp_conn := g_media.mgcp_conn[cid];
+ sdp := valueof(ts_SDP(mgcp_conn.peer.host, mgcp_conn.peer.host, "foo", "21",
+ mgcp_conn.peer.port_nr, { int2str(mgcp_conn.rtp_pt) },
+ {valueof(ts_SDP_rtpmap(mgcp_conn.rtp_pt,
+ mgcp_conn.mime_type & "/" &
+ int2str(mgcp_conn.sample_rate))),
+ valueof(ts_SDP_ptime(mgcp_conn.ptime)) } ));
+ g_media.mgcp_conn[cid].mdcx_seen := g_media.mgcp_conn[cid].mdcx_seen + 1;
+ return ts_MDCX_ACK(mgcp_cmd.line.trans_id, mgcp_conn.conn_id, sdp);
+}
+
+function tr_MGCP_RecvFrom_any(template MgcpMessage msg)
+runs on MSC_ConnHdlr return template MGCP_RecvFrom {
+ var template MGCP_RecvFrom mrf := {
+ connId := ?,
+ remName := ?,
+ remPort := ?,
+ locName := ?,
+ locPort := ?,
+ msg := msg
+ }
+ return mrf;
+}
+
/* altstep for handling of MGCP media related commands. Activated by as_Media() to test
* MGW level media handling */
altstep as_Media_mgw(boolean norepeat := false) runs on MSC_ConnHdlr {
var MgcpCommand mgcp_cmd;
- var MgcpOsmuxCID osmux_cid;
+ var template MgcpResponse mgcp_resp;
+ var MGCP_RecvFrom mrf;
+ var template MgcpMessage msg_crcx := {
+ command := tr_CRCX
+ }
+ var template MgcpMessage msg_mdcx := {
+ command := tr_MDCX
+ }
+ var template MgcpMessage msg_resp;
- [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
- var SDP_Message sdp;
- var integer cid := f_get_free_mgcp_conn();
- if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard)) {
- if (cid != 0) {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "MGCP wildcard EP only works in first CRCX");
- }
- /* we keep the endpoint name allocated during MediaState_init */
- } else {
- /* Call Agent allocated endpoint, trust/use it always */
- g_media.mgcp_ep := mgcp_cmd.line.ep;
+ [g_pars.aoip] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
+ mgcp_resp := f_rx_crcx(mgcp_cmd);
+ MGCP.send(mgcp_resp);
+ if(norepeat == false) {
+ repeat;
}
- if (isvalue(mgcp_cmd.sdp)) {
- sdp := mgcp_cmd.sdp;
- g_media.mgcp_conn[cid].peer.host := sdp.connection.conn_addr.addr;
- g_media.mgcp_conn[cid].peer.port_nr := sdp.media_list[0].media_field.ports.port_number;
+ }
+
+ [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_crcx)) -> value mrf {
+ mgcp_resp := f_rx_crcx(mrf.msg.command);
+ msg_resp := {
+ response := mgcp_resp
}
- var MgcpConnState mgcp_conn := g_media.mgcp_conn[cid];
- sdp := valueof(ts_SDP(mgcp_conn.mgw.host, mgcp_conn.mgw.host, "foo", "21",
- mgcp_conn.mgw.port_nr, { int2str(mgcp_conn.rtp_pt) },
- {valueof(ts_SDP_rtpmap(mgcp_conn.rtp_pt,
- mgcp_conn.mime_type & "/" &
- int2str(mgcp_conn.sample_rate))),
- valueof(ts_SDP_ptime(mgcp_conn.ptime)) } ));
- var template MgcpResponse mgcp_resp;
- if (g_pars.use_osmux and f_MgcpCmd_contains_par(mgcp_cmd, "X-OSMUX")) {
- osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
- mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, mgcp_conn.conn_id, osmux_cid, sdp);
- } else {
- mgcp_resp := ts_CRCX_ACK(mgcp_cmd.line.trans_id, mgcp_conn.conn_id, sdp);
+ MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
+ if(norepeat == false) {
+ repeat;
}
- f_mgcp_par_append(mgcp_resp.params, ts_MgcpParSpecEP(g_media.mgcp_ep));
+ }
+
+ [g_pars.aoip] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
+ mgcp_resp := f_rx_mdcx(mgcp_cmd);
MGCP.send(mgcp_resp);
- g_media.mgcp_conn[cid].crcx_seen := g_media.mgcp_conn[cid].crcx_seen + 1;
if(norepeat == false) {
repeat;
}
+ }
+
+ [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_mdcx)) -> value mrf {
+ mgcp_resp := f_rx_mdcx(mrf.msg.command);
+ msg_resp := {
+ response := mgcp_resp
}
- [] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
- var SDP_Message sdp;
- var integer cid := f_get_mgcp_conn(f_MgcpCmd_extract_conn_id(mgcp_cmd));
- if (isvalue(mgcp_cmd.sdp)) {
- sdp := mgcp_cmd.sdp;
- g_media.mgcp_conn[cid].peer.host := sdp.connection.conn_addr.addr;
- g_media.mgcp_conn[cid].peer.port_nr := sdp.media_list[0].media_field.ports.port_number;
- } else {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "MDCX has no [recognizable] SDP");
- }
- var MgcpConnState mgcp_conn := g_media.mgcp_conn[cid];
- sdp := valueof(ts_SDP(mgcp_conn.peer.host, mgcp_conn.peer.host, "foo", "21",
- mgcp_conn.peer.port_nr, { int2str(mgcp_conn.rtp_pt) },
- {valueof(ts_SDP_rtpmap(mgcp_conn.rtp_pt,
- mgcp_conn.mime_type & "/" &
- int2str(mgcp_conn.sample_rate))),
- valueof(ts_SDP_ptime(mgcp_conn.ptime)) } ));
- MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, mgcp_conn.conn_id, sdp));
- g_media.mgcp_conn[cid].mdcx_seen := g_media.mgcp_conn[cid].mdcx_seen + 1;
+ MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
if(norepeat == false) {
repeat;
}
@@ -357,9 +416,19 @@ type component MSC_ConnHdlr extends RAN_ConnHdlr, RSL_DchanHdlr, MGCP_ConnHdlr {
port RAN_PROC_PT RAN;
port TELNETasp_PT BSCVTY;
+ /* Proxy MGCP-over-IPA and MGCP-over-UDP */
+ //var MGCP_Adapter_CT vc_MGCP_UDP;
+ port IPA_MGCP_PT MGCP_MSC_CLIENT;
+ var integer g_trans_id := 0;
+ var MgcpConnectionId g_mgcp_conn_id;
+
var MediaState g_media;
var TestHdlrParams g_pars;
+ var charstring host_bts := "127.0.0.2";
+ var charstring host_mgw := "127.0.0.3";
+ var charstring host_msc := "127.0.0.4";
+
var boolean g_vty_initialized := false;
}
@@ -374,6 +443,12 @@ function f_MscConnHdlr_init(integer i, HostName bts, HostName mgw, BSSMAP_FIELD_
}
}
+private function get_next_trans_id() runs on MSC_ConnHdlr return MgcpTransId {
+ var MgcpTransId tid := int2str(g_trans_id);
+ g_trans_id := g_trans_id + 1;
+ return tid;
+}
+
/* Callback function from general RAN_Emulation whenever a connectionless
* BSSMAP message arrives. Can retunr a PDU_BSSAP that should be sent in return */
private function UnitdataCallback(PDU_BSSAP bssap)
@@ -846,6 +921,31 @@ function f_ass_patch_lcls(inout template (omit) PDU_BSSAP ass_tpl,
}
}
+/* Send a MGCP request + receive a (matching!) response */
+function mgcp_transceive_mgw(template MgcpCommand cmd, template MgcpResponse resp := ?) runs on MSC_ConnHdlr {
+ template MgcpResponse resp_any := ?
+ var MgcpResponse resp_val;
+ resp.line.trans_id := cmd.line.trans_id;
+ timer T := 5.0;
+
+ BSSAP.send(cmd);
+ T.start;
+ alt {
+ [] as_Media_mgw();
+ [] BSSAP.receive(resp) -> value resp_val { }
+ [] BSSAP.receive(resp_any) {
+ setverdict(fail, "Response didn't match template");
+ mtc.stop;
+ }
+ [] BSSAP.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for response to ", cmd);
+ mtc.stop;
+ }
+ }
+ T.stop;
+}
+
/* Helper function to check if the activity on the MGCP matches what we
* expected */
function f_check_mgcp_expectations() runs on MSC_ConnHdlr {
@@ -878,7 +978,7 @@ runs on MSC_ConnHdlr {
codecType := FR_AMR;
}
- f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", codecType);
+ f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw, codecType);
/* patch in the LCLS related items, as needed */
f_ass_patch_lcls(ass_tpl, exp_ass_cpl);
@@ -959,17 +1059,10 @@ runs on MSC_ConnHdlr {
g_media.mgcp_conn[1].mdcx_seen_exp := 0;
} else if (st.voice_call) {
/* For voice calls we expect the following MGCP activity */
- if (g_pars.aoip == false) {
- g_media.mgcp_conn[0].crcx_seen_exp := 1;
- g_media.mgcp_conn[0].mdcx_seen_exp := 1;
- g_media.mgcp_conn[1].crcx_seen_exp := 0;
- g_media.mgcp_conn[1].mdcx_seen_exp := 0;
- } else {
- g_media.mgcp_conn[0].crcx_seen_exp := 1;
- g_media.mgcp_conn[0].mdcx_seen_exp := 1;
- g_media.mgcp_conn[1].crcx_seen_exp := 1;
- g_media.mgcp_conn[1].mdcx_seen_exp := 0;
- }
+ g_media.mgcp_conn[0].crcx_seen_exp := 1;
+ g_media.mgcp_conn[0].mdcx_seen_exp := 1;
+ g_media.mgcp_conn[1].crcx_seen_exp := 1;
+ g_media.mgcp_conn[1].mdcx_seen_exp := 0;
}
f_create_mgcp_expect(mgcpcrit);
@@ -1028,6 +1121,24 @@ runs on MSC_ConnHdlr {
}
}
+ if (not exp_fail and st.voice_call and not g_pars.aoip) {
+ /* With SCCPLite, connect to BSC-located MGW using a CRCX + SDP.
+ It is sent in MGCP over IPA in the BSC<->MSC (BSC-NAT)
+ connection. BSC will forward it to its MGW. */
+ var template MgcpCommand cmd;
+ var template MgcpResponse resp := ?;
+ var integer cic := f_bssmap_ie_cic_2_int(ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode);
+ var MgcpEndpoint ep := int2str(cic) & "@mgw"; /* 1: matches value configured in BSC_Tests.ttcn pass in AssignReq */
+ var MgcpCallId call_id := '51234'H;
+ var SDP_attribute_list attributes := { valueof(ts_SDP_ptime(20)) };
+ cmd := ts_CRCX(get_next_trans_id(), ep, "sendrecv", call_id);
+ cmd.sdp := ts_SDP(host_msc, host_mgw, "23", "42",
+ 14000, { int2str(g_media.mgcp_conn[1].rtp_pt) },
+ { valueof(ts_SDP_ptime(20)) });
+ g_mgcp_conn_id := f_mgcp_alloc_conn_id();
+ mgcp_transceive_mgw(cmd, tr_CRCX_ACK);
+ }
+
f_check_mgcp_expectations();
if (st.is_assignment and st.assignment_done) {
diff --git a/library/BSSMAP_Templates.ttcn b/library/BSSMAP_Templates.ttcn
index b377358..9015680 100644
--- a/library/BSSMAP_Templates.ttcn
+++ b/library/BSSMAP_Templates.ttcn
@@ -402,6 +402,11 @@ template (value) BSSMAP_IE_CircuitIdentityCode ts_BSSMAP_IE_CIC(uint11_t span, u
cicLow := bit2oct((substr(int2bit(span, 11), 8, 3) << 5) & int2bit(ts, 5))
}
+function f_bssmap_ie_cic_2_int(BSSMAP_IE_CircuitIdentityCode cic_ie) return integer {
+ var integer cic := (oct2int(cic_ie.cicHigh) * 256) + oct2int(cic_ie.cicLow);
+ return cic;
+}
+
template (value) BSSMAP_IE_AoIP_TransportLayerAddress ts_BSSMAP_IE_AoIP_TLA(BSSMAP_FIELD_IPAddress addr,
uint16_t udp_port,
integer len) := {
diff --git a/library/MGCP_CodecPort.ttcn b/library/MGCP_CodecPort.ttcn
index d33afe1..8614eef 100644
--- a/library/MGCP_CodecPort.ttcn
+++ b/library/MGCP_CodecPort.ttcn
@@ -41,11 +41,33 @@ module MGCP_CodecPort {
MgcpMessage msg
}
+ type record MGCP_SendTo {
+ ConnectionId connId,
+ HostName remName,
+ PortNumber remPort,
+ MgcpMessage msg
+ };
+
template MGCP_Send t_MGCP_Send(template ConnectionId connId, template MgcpMessage msg) := {
connId := connId,
msg := msg
}
+ template MGCP_SendTo t_MGCP_SendTo(template ConnectionId connId, HostName remName,
+ PortNumber remPort,template MgcpMessage msg) := {
+ connId := connId,
+ remName := remName,
+ remPort := remPort,
+ msg := msg
+ }
+
+ template MGCP_SendTo t_MGCP_SendToMrf(MGCP_RecvFrom mrf,template MgcpMessage msg) := {
+ connId := mrf.connId,
+ remName := mrf.remName,
+ remPort := mrf.remPort,
+ msg := msg
+ }
+
private function IPL4_to_MGCP_RecvFrom(in ASP_RecvFrom pin, out MGCP_RecvFrom pout) {
pout.connId := pin.connId;
pout.remName := pin.remName;
@@ -65,13 +87,23 @@ module MGCP_CodecPort {
pout.msg := char2oct(enc_MgcpMessage(pin.msg));
} with { extension "prototype(fast)" };
+ private function MGCP_to_IPL4_SendTo(in MGCP_SendTo pin, out ASP_SendTo out_ud) {
+ out_ud.connId := pin.connId;
+ out_ud.remName := pin.remName;
+ out_ud.remPort := pin.remPort;
+ out_ud.proto := { udp := {} };
+ out_ud.msg := char2oct(enc_MgcpMessage(pin.msg));
+ } with { extension "prototype(fast)" };
+
type port MGCP_CODEC_PT message {
- out MGCP_Send;
+ out MGCP_Send,
+ MGCP_SendTo;
in MGCP_RecvFrom,
ASP_ConnId_ReadyToRelease,
ASP_Event;
} with { extension "user IPL4asp_PT
- out(MGCP_Send -> ASP_Send:function(MGCP_to_IPL4_Send))
+ out(MGCP_Send -> ASP_Send:function(MGCP_to_IPL4_Send);
+ MGCP_SendTo -> ASP_SendTo: function(MGCP_to_IPL4_SendTo))
in(ASP_RecvFrom -> MGCP_RecvFrom: function(IPL4_to_MGCP_RecvFrom);
ASP_ConnId_ReadyToRelease -> ASP_ConnId_ReadyToRelease: simple;
ASP_Event -> ASP_Event: simple)"
diff --git a/library/MGCP_Emulation.ttcn b/library/MGCP_Emulation.ttcn
index 23cfeb4..494b171 100644
--- a/library/MGCP_Emulation.ttcn
+++ b/library/MGCP_Emulation.ttcn
@@ -37,8 +37,11 @@ import from Osmocom_Types all;
import from IPL4asp_Types all;
type component MGCP_ConnHdlr {
+ /* Simple send/recv without caring about peer addr+port. Used with multi_conn_mode=false. */
port MGCP_Conn_PT MGCP;
- /* procedure based port to register for incoming connections */
+ /* Handle multiple connections concurrently. Used with multi_conn_mode=true. */
+ port MGCP_Conn_Multi_PT MGCP_MULTI;
+ /* procedure based port to register for incoming connections. */
port MGCPEM_PROC_PT MGCP_PROC;
}
@@ -47,6 +50,11 @@ type port MGCP_Conn_PT message {
inout MgcpCommand, MgcpResponse;
} with { extension "internal" };
+/* port between individual per-connection components and this dispatcher */
+type port MGCP_Conn_Multi_PT message {
+ inout MGCP_RecvFrom, MGCP_SendTo;
+} with { extension "internal" };
+
/* represents a single MGCP Endpoint */
type record EndpointData {
MGCP_ConnHdlr comp_ref,
@@ -63,6 +71,8 @@ type component MGCP_Emulation_CT {
* MGCP_Emulation_CT.main needs to figure out what messages
* to send where with CLIENT.send() to vc_conn */
port MGCP_Conn_PT MGCP_CLIENT;
+ /* This one is used with multi_conn_mode=true and allows differentiating UDP sockets */
+ port MGCP_Conn_Multi_PT MGCP_CLIENT_MULTI;
/* currently tracked connections */
var EndpointData MgcpEndpointTable[16];
var MgcpTransIds MgcpPendingTrans := {};
@@ -73,6 +83,8 @@ type component MGCP_Emulation_CT {
var charstring g_mgcp_id;
var integer g_mgcp_conn_id := -1;
+
+ var MGCP_conn_parameters g_pars;
}
type function MGCPCreateCallback(MgcpCommand cmd, charstring id)
@@ -90,7 +102,8 @@ type record MGCP_conn_parameters {
HostName callagent_ip,
PortNumber callagent_udp_port,
HostName mgw_ip,
- PortNumber mgw_udp_port
+ PortNumber mgw_udp_port,
+ boolean multi_conn_mode
}
function tr_MGCP_RecvFrom_R(template MgcpMessage msg)
@@ -224,14 +237,23 @@ runs on MGCP_Emulation_CT {
}
}
+private function f_forward_to_client(MGCP_RecvFrom mrf, MGCP_ConnHdlr vc_conn) runs on MGCP_Emulation_CT {
+ if (g_pars.multi_conn_mode) {
+ MGCP_CLIENT_MULTI.send(mrf) to vc_conn;
+ } else {
+ MGCP_CLIENT.send(mrf.msg.command) to vc_conn;
+ }
+}
+
function main(MGCPOps ops, MGCP_conn_parameters p, charstring id) runs on MGCP_Emulation_CT {
var Result res;
+ g_pars := p;
g_mgcp_id := id;
f_ep_table_init();
f_expect_table_init();
map(self:MGCP, system:MGCP_CODEC_PT);
- if (p.callagent_udp_port == -1) {
+ if (p.multi_conn_mode or p.callagent_udp_port == -1) {
res := MGCP_CodecPort_CtrlFunct.f_IPL4_listen(MGCP, p.mgw_ip, p.mgw_udp_port, { udp:={} });
} else {
res := MGCP_CodecPort_CtrlFunct.f_IPL4_connect(MGCP, p.callagent_ip, p.callagent_udp_port, p.mgw_ip, p.mgw_udp_port, -1, { udp:={} });
@@ -246,6 +268,7 @@ function main(MGCPOps ops, MGCP_conn_parameters p, charstring id) runs on MGCP_E
var MGCP_ConnHdlr vc_conn;
var ExpectCriteria crit;
var MGCP_RecvFrom mrf;
+ var MGCP_SendTo mst;
var MgcpMessage msg;
var MgcpCommand cmd;
var MgcpResponse resp;
@@ -253,7 +276,7 @@ function main(MGCPOps ops, MGCP_conn_parameters p, charstring id) runs on MGCP_E
alt {
/* MGCP from client */
- [] MGCP_CLIENT.receive(MgcpResponse:?) -> value resp sender vc_conn {
+ [not p.multi_conn_mode] MGCP_CLIENT.receive(MgcpResponse:?) -> value resp sender vc_conn {
msg := {
response := resp
};
@@ -265,9 +288,23 @@ function main(MGCPOps ops, MGCP_conn_parameters p, charstring id) runs on MGCP_E
/* TODO: check which ConnectionID client has allocated + store in table? */
MGCP.send(t_MGCP_Send(g_mgcp_conn_id, msg));
}
+
+ /* MGCP from client in Multi Conn mode */
+ [p.multi_conn_mode] MGCP_CLIENT_MULTI.receive(MGCP_SendTo:?) -> value mst sender vc_conn {
+ /* If this is the resposne to a pending CRCX, extract Endpoint and store in table */
+ if (f_trans_id_was_pending(mst.msg.response.line.trans_id)) {
+ f_ep_table_add(vc_conn, f_mgcp_ep(mst.msg));
+ }
+ /* Pass message through */
+ /* TODO: check which ConnectionID client has allocated + store in table? */
+ MGCP.send(mst);
+ }
[] MGCP.receive(tr_MGCP_RecvFrom_R(?)) -> value mrf {
- if (p.callagent_udp_port == -1) {
- /* we aren't yet connected to the remote side port, let's fix this */
+ if (not p.multi_conn_mode and p.callagent_udp_port == -1) {
+ /* we aren't yet connected to the remote side
+ port, let's fix this. This way upper layers
+ can use Send/Recv without caring about UDP
+ src/dst addr + port */
p.callagent_udp_port := mrf.remPort;
res := MGCP_CodecPort_CtrlFunct.f_IPL4_connect(MGCP, p.callagent_ip, p.callagent_udp_port, p.mgw_ip, p.mgw_udp_port, g_mgcp_conn_id, { udp:={} });
if (not ispresent(res.connId)) {
@@ -279,7 +316,7 @@ function main(MGCPOps ops, MGCP_conn_parameters p, charstring id) runs on MGCP_E
cmd := mrf.msg.command;
if (f_ep_known(cmd.line.ep)) {
vc_conn := f_comp_by_ep(cmd.line.ep);
- MGCP_CLIENT.send(cmd) to vc_conn;
+ f_forward_to_client(mrf, vc_conn);
} else {
if (cmd.line.verb == "CRCX") {
vc_conn := ops.create_cb.apply(cmd, id);
@@ -290,12 +327,12 @@ function main(MGCPOps ops, MGCP_conn_parameters p, charstring id) runs on MGCP_E
/* add this transaction to list of pending transactions */
MgcpPendingTrans := MgcpPendingTrans & {cmd.line.trans_id};
}
- MGCP_CLIENT.send(cmd) to vc_conn;
+ f_forward_to_client(mrf, vc_conn);
} else {
/* connectionless MGCP, i.e. messages without ConnectionId */
var template MgcpMessage r := ops.unitdata_cb.apply(mrf.msg);
if (isvalue(r)) {
- MGCP.send(t_MGCP_Send(g_mgcp_conn_id, r));
+ MGCP.send(t_MGCP_SendToMrf(mrf, r));
}
}
}
diff --git a/msc/MSC_Tests.ttcn b/msc/MSC_Tests.ttcn
index 2c898fc..5e1e0b5 100644
--- a/msc/MSC_Tests.ttcn
+++ b/msc/MSC_Tests.ttcn
@@ -230,7 +230,8 @@ function f_init_mgcp(charstring id) runs on MTC_CT {
callagent_ip := mp_msc_ip,
callagent_udp_port := -1,
mgw_ip := mp_mgw_ip,
- mgw_udp_port := mp_mgw_port
+ mgw_udp_port := mp_mgw_port,
+ multi_conn_mode := false
}
vc_MGCP := MGCP_Emulation_CT.create(id);