aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2019-06-18 17:21:52 +0200
committerlaforge <laforge@gnumonks.org>2019-06-24 13:53:25 +0000
commit1a026a52d3e7c2914f8775c15245dbfbef5bdd40 (patch)
treef3708dc7420f058a69c062db78579a86a178264e
parent513b831cdacb2ff41fe87f2770fb0b96a64d4ce4 (diff)
lib/mgcp: Add new port with support to handle multiple MGCP sockets
* Some scenarios like MGW BSC-attached in SCCPlite require handling of 2 MGCP-over-UDP sockets in MGCP Emulation: 1 for regular libosmomgcp-client from osmo-bsc and another one from the forward socket from osmo-bsc (of MGCP-over-IPA messages communicated with MSC). * Old port is kept for backward compatibility with other tests and enabled by default. It's also interesting to keep it because it makes tests without special needs (2 sockets) to use the old port/API which produces simpler code to read and mantain. * Users of the new port have to enable multi_conn_mode parameter and expect to interact with port MGCP_CLIENT_MULTI instead of MGCP_CLIENT, which will offer messages containing information about the UDP connection being used by that message. Change-Id: Ic0ba8c5cde068c07671512a83095d83e28b86746
-rw-r--r--bsc/BSC_Tests.ttcn3
-rw-r--r--library/MGCP_CodecPort.ttcn36
-rw-r--r--library/MGCP_Emulation.ttcn55
-rw-r--r--msc/MSC_Tests.ttcn3
4 files changed, 84 insertions, 13 deletions
diff --git a/bsc/BSC_Tests.ttcn b/bsc/BSC_Tests.ttcn
index 976bc461..4c86e51f 100644
--- a/bsc/BSC_Tests.ttcn
+++ b/bsc/BSC_Tests.ttcn
@@ -294,7 +294,8 @@ 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,
+ multi_conn_mode := false
};
vc_MGCP := MGCP_Emulation_CT.create(id);
diff --git a/library/MGCP_CodecPort.ttcn b/library/MGCP_CodecPort.ttcn
index d33afe18..8614eef1 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 23cfeb4a..494b1714 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 b00e032e..4b00e345 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);