ipa: Further progress on the bsc-nat test suite
diff --git a/ipa/BSC_MS_Simulation.ttcn b/ipa/BSC_MS_Simulation.ttcn
index c33e848..24ac4bc 100644
--- a/ipa/BSC_MS_Simulation.ttcn
+++ b/ipa/BSC_MS_Simulation.ttcn
@@ -43,9 +43,12 @@
 	/* 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 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);
+
 	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));
diff --git a/ipa/MSC_ConnectionHandler.ttcn b/ipa/MSC_ConnectionHandler.ttcn
index 641a832..53123fe 100644
--- a/ipa/MSC_ConnectionHandler.ttcn
+++ b/ipa/MSC_ConnectionHandler.ttcn
@@ -7,6 +7,10 @@
 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 */
@@ -15,6 +19,11 @@
 	var uint5_t g_e1_timeslot;
 	/* 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
@@ -49,30 +58,98 @@
 	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
+}
+
+private function f_mgcp_alloc_tid() return MgcpTransId {
+	return int2str(float2int(rnd()*2147483647.0));
+}
+
+private function f_mgcp_alloc_call_id() return MgcpCallId {
+	return int2hex(float2int(rnd()*2147483647.0), 8);
+}
+
+function extract_conn_id(MgcpResponse resp) return MgcpConnectionId {
+	var integer i;
+	for (i := 0; i < lengthof(resp.params); i := i + 1) {
+		var MgcpParameter par := resp.params[i];
+		if (par.code == "I") {
+			return str2hex(par.val);
+		}
+	}
+	setverdict(fail);
+	return '00000000'H;
+}
+
 /* main function processing various incoming events */
 function main(integer connection_id, integer timeslot) runs on MSC_ConnHdlr {
-	g_sccp_conn_id := connection_id;
+	var MgcpResponse mgcp_rsp;
+
 	g_e1_timeslot := 1; /* FIXME */
 
+	g_sccp_conn_id := connection_id;
+	g_call_id := f_mgcp_alloc_call_id();
+	g_ep_name := hex2str(int2hex(g_e1_timeslot, 1)) & "@mgw";
+
 	while (true) {
 		var PDU_BSSAP bssap;
 		alt {
 		/* new SCCP-level connection indication from BSC */
-		[] BSSAP.receive(tr_BSSMAP_ComplL3) -> value bssap {
+		[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, g_e1_timeslot));
-			/* FIXME: Send MGCP */
+			}
+		[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_AssignmentCompl) {
-		}
 		[] 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 := 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(0));
+			}
+
+		/* CLEAR COMPLETE from BSS (response to CLEAR COMMAND) */
+		[g_state == MSC_STATE_WAIT_CLEAR_COMPL] BSSAP.receive(ts_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) {
+			setverdict(pass);
+			self.stop;
+			}
+
 		/* TODO: CLEAR REQUEST from BSS */
-		/* TODO: CLEAR COMPLETE from BSS (response to CLEAR COMMAND) */
 
 		[] BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {
+			setverdict(fail);
 			self.stop;
 			}
 
diff --git a/ipa/MSC_Simulation.ttcn b/ipa/MSC_Simulation.ttcn
index 8c94188..0198350 100755
--- a/ipa/MSC_Simulation.ttcn
+++ b/ipa/MSC_Simulation.ttcn
@@ -46,6 +46,9 @@
 	/* connect BSSNAP 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);
+
 	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));
diff --git a/ipa/gen_links.sh b/ipa/gen_links.sh
index be11ec0..7dd5ed2 100755
--- a/ipa/gen_links.sh
+++ b/ipa/gen_links.sh
@@ -16,7 +16,7 @@
 #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"
+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
@@ -35,7 +35,7 @@
 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 -s SCCP_Mapping.ttcnpp SCCP_Mapping.ttcn
+ln -sf SCCP_Mapping.ttcnpp SCCP_Mapping.ttcn
 
 DIR=$BASEDIR/titan.ProtocolModules.BSSMAP_v11.2.0/src
 FILES="BSSAP_Types.ttcn"
@@ -45,7 +45,15 @@
 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"
+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"
 gen_links $DIR $FILES
diff --git a/ipa/regen_makefile.sh b/ipa/regen_makefile.sh
index 1acda32..be79a35 100755
--- a/ipa/regen_makefile.sh
+++ b/ipa/regen_makefile.sh
@@ -2,7 +2,7 @@
 
 MAIN=IPA_Test.ttcn
 
-FILES="*.ttcn SCCP_EncDec.cc IPA_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc"
+FILES="*.ttcn SCCP_EncDec.cc IPA_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc RTP_EncDec.cc SDP_EncDec *.c"
 
 ttcn3_makefilegen -l -f $MAIN $FILES
 sed -i -e 's/# TTCN3_DIR = /TTCN3_DIR = \/usr/' Makefile
diff --git a/library/BSSMAP_Emulation.ttcn b/library/BSSMAP_Emulation.ttcn
index 5cf5342..7a84133 100644
--- a/library/BSSMAP_Emulation.ttcn
+++ b/library/BSSMAP_Emulation.ttcn
@@ -4,7 +4,9 @@
 import from SCCPasp_Types all;
 import from BSSAP_Types all;
 import from BSSMAP_Templates all;
-//import from MSC_ConnectionHandler all;
+import from MGCP_Types all;
+import from MGCP_Templates all;
+import from IPA_Emulation all;
 
 /* General "base class" component definition, of which specific implementations
  * derive themselves by means of the "extends" feature */
@@ -29,7 +31,7 @@
 
 /* port between individual per-connection components and this dispatcher */
 type port BSSAP_Conn_PT message {
-	inout PDU_BSSAP, BSSAP_Conn_Prim, BSSAP_Conn_Req;
+	inout PDU_BSSAP, BSSAP_Conn_Prim, BSSAP_Conn_Req, MgcpCommand, MgcpResponse;
 } with { extension "internal" };
 
 
@@ -37,7 +39,11 @@
 type record ConnectionData {
 	/* reference to the instance of the per-connection component */
 	BSSAP_ConnHdlr	comp_ref,
-	integer		sccp_conn_id
+	integer		sccp_conn_id,
+	/* most recent MGCP transaction ID (Used on MSC side) */
+	MgcpTransId	mgcp_trans_id optional,
+	/* CIC that has been used for voice of this channel (BSC side) */
+	integer		cic optional
 }
 
 type component BSSMAP_Emulation_CT {
@@ -45,6 +51,8 @@
 	port SCCPasp_PT SCCP;
 	/* BSSAP port to the per-connection clients */
 	port BSSAP_Conn_PT CLIENT;
+	/* MGCP port */
+	port IPA_MGCP_PT MGCP;
 
 	/* use 16 as this is also the number of SCCP connections that SCCP_Emulation can handle */
 	var ConnectionData ConnectionTable[16];
@@ -85,6 +93,56 @@
 	self.stop;
 }
 
+/* resolve component reference by CIC */
+private function f_comp_by_mgcp_tid(MgcpTransId tid)
+runs on BSSMAP_Emulation_CT return BSSAP_ConnHdlr {
+	var integer i;
+	for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
+		if (ConnectionTable[i].mgcp_trans_id == tid) {
+			return ConnectionTable[i].comp_ref;
+		}
+	}
+	log("BSSMAP Connection table not found by MGCP Transaction ID ", tid);
+	self.stop;
+}
+
+private function f_comp_store_mgcp_tid(BSSAP_ConnHdlr client, MgcpTransId tid)
+runs on BSSMAP_Emulation_CT {
+	var integer i;
+	for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
+		if (ConnectionTable[i].comp_ref == client) {
+			ConnectionTable[i].mgcp_trans_id := tid;
+			return;
+		}
+	}
+	log("BSSMAP Connection table not found by component ", client);
+	self.stop;
+}
+
+private function f_comp_by_cic(integer cic)
+runs on BSSMAP_Emulation_CT return BSSAP_ConnHdlr {
+	var integer i;
+	for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
+		if (ConnectionTable[i].cic == cic) {
+			return ConnectionTable[i].comp_ref;
+		}
+	}
+	log("BSSMAP Connection table not found by CIC ", cic);
+	self.stop;
+}
+
+private function f_comp_store_cic(BSSAP_ConnHdlr client, integer cic)
+runs on BSSMAP_Emulation_CT {
+	var integer i;
+	for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
+		if (ConnectionTable[i].comp_ref == client) {
+			ConnectionTable[i].cic := cic;
+			return;
+		}
+	}
+	log("BSSMAP Connection table not found by component ", client);
+}
+
 /* resolve connection ID by component reference */
 private function f_conn_id_by_comp(BSSAP_ConnHdlr client)
 runs on BSSMAP_Emulation_CT return integer {
@@ -113,6 +171,8 @@
 	for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) {
 		ConnectionTable[i].comp_ref := null;
 		ConnectionTable[i].sccp_conn_id := -1;
+		ConnectionTable[i].mgcp_trans_id := omit;
+		ConnectionTable[i].cic := omit;
 	}
 }
 
@@ -178,6 +238,8 @@
 		var BSSAP_Conn_Req creq;
 		var BSSAP_ConnHdlr vc_conn;
 		var PDU_BSSAP bssap;
+		var MgcpCommand mgcp_req;
+		var MgcpResponse mgcp_resp;
 
 		alt {
 		/* SCCP -> Client: UNIT-DATA (connectionless SCCP) from a BSC */
@@ -266,14 +328,62 @@
 
 		[] CLIENT.receive(PDU_BSSAP:?) -> value bssap sender vc_conn {
 			var integer conn_id := f_conn_id_by_comp(vc_conn);
+			/* MSC Side: If this is an assignment command, store CIC */
+			if (ischosen(bssap.pdu.bssmap.assignmentRequest) and
+			    ispresent(bssap.pdu.bssmap.assignmentRequest.circuitIdentityCode)) {
+				var BSSMAP_IE_CircuitIdentityCode cic_ie :=
+					bssap.pdu.bssmap.assignmentRequest.circuitIdentityCode;
+				var integer cic := (oct2int(cic_ie.cicHigh) * 256) + oct2int(cic_ie.cicLow);
+				f_comp_store_cic(vc_conn, cic);
+			}
 			/* encode + send it to dispatcher */
 			var octetstring userdata := enc_PDU_BSSAP(bssap);
 			SCCP.send(t_ASP_N_DATA_req(userdata, conn_id, omit));
 			}
 
+		/* Handling of MGCP in IPA SCCPLite case.  This predates 3GPP AoIP
+		 * and uses a MGCP session in parallel to BSSAP.  BSSAP uses CIC
+		 * as usual, and MGCP uses "CIC@mgw" endpoint naming, where CIC
+		 * is printed as hex string, e.g. a@mgw for CIC 10 */
+
+		/* CLIENT -> MGCP */
+		[] CLIENT.receive(MgcpCommand:?) -> value mgcp_req sender vc_conn {
+			/* MGCP request from Handler (we're MSC) */
+			/* store the transaction ID we've seen */
+			f_comp_store_mgcp_tid(vc_conn, mgcp_req.line.trans_id);
+			/* simply forward any MGCP from the client to the port */
+			MGCP.send(mgcp_req);
+			}
+		[] CLIENT.receive(MgcpResponse:?) -> value mgcp_resp sender vc_conn {
+			/* MGCP response from Handler (we're BSC/MGW) */
+			/* simply forward any MGCP from the client to the port */
+			MGCP.send(mgcp_resp);
+			}
+
+		/* MGCP -> CLIENT */
+		[] MGCP.receive(MgcpCommand:?) -> value mgcp_req {
+			/* MGCP request from network side (we're BSC/MGW) */
+			/* Extract CIC from local part of endpoint name */
+			var integer cic := f_mgcp_ep_extract_cic(mgcp_req.line.ep);
+			/* Resolve the vc_conn by the CIC */
+			vc_conn := f_comp_by_cic(cic);
+			CLIENT.send(mgcp_req) to vc_conn;
+			}
+		[] MGCP.receive(MgcpResponse:?) -> value mgcp_resp {
+			/* MGCP response from network side (we're MSC) */
+			/* Resolve the vc_conn by the transaction ID */
+			vc_conn := f_comp_by_mgcp_tid(mgcp_resp.line.trans_id);
+			CLIENT.send(mgcp_resp) to vc_conn;
+			}
+
 		}
 	}
 }
 
+private function f_mgcp_ep_extract_cic(charstring inp) return integer {
+	var charstring local_part := regexp(inp, "(.*)@(.*)", 0);
+	return hex2int(str2hex(local_part));
+
+}
 
 }
diff --git a/library/IPA_CodecPort.ttcn b/library/IPA_CodecPort.ttcn
index de47a16..3c68e22 100644
--- a/library/IPA_CodecPort.ttcn
+++ b/library/IPA_CodecPort.ttcn
@@ -18,6 +18,13 @@
 		octetstring	msg
 	}
 
+	template IPA_Send t_IPA_Send(ConnectionId conn_id, IpaStreamId stream_id,
+				octetstring msg, template IpaExtStreamId stream_id_ext := omit) := {
+		connId := conn_id,
+		streamId := stream_id,
+		streamIdExt := stream_id_ext,
+		msg := msg
+	}
 
 	/* 'stream' contains the octets received so far, we must return the total length */
 	function f_IPA_getMsgLen(in octetstring stream, inout ro_integer args) return integer {
diff --git a/library/IPA_Emulation.ttcn b/library/IPA_Emulation.ttcn
index 57edb00..3b8d931 100644
--- a/library/IPA_Emulation.ttcn
+++ b/library/IPA_Emulation.ttcn
@@ -7,6 +7,8 @@
 import from MTP3asp_Types all;
 import from MTP3asp_PortType all;
 
+import from MGCP_Types all;
+
 /*
 modulepar {
 }
@@ -19,7 +21,7 @@
 
 type record ASP_IPA_Unitdata {
 	IpaStreamId	streamId,
-	IpaStreamIdExt	streamIdExt optional,
+	IpaExtStreamId	streamIdExt optional,
 	octetstring	payload
 }
 
@@ -27,16 +29,24 @@
 	inout ASP_IPA_Unitdata;
 } with { extension "internal" }
 
+type port IPA_MGCP_PT message {
+	inout MgcpCommand, MgcpResponse;
+} with { extension "internal" }
+
 type component IPA_Emulation_CT {
 	/* down-facing port to IPA codec port */
 	port IPA_CODEC_PT IPA_PORT;
 	/* up-facing port to SCCP */
 	port MTP3asp_SP_PT MTP3_SP_PORT;
+	/* up-facing port for MGCP */
+	port IPA_MGCP_PT IPA_MGCP_PORT;
 	/* up-facing port for other streams */
 	port IPA_SP_PT IPA_SP_PORT;
 
 	var boolean g_initialized := false;
 	var ConnectionId g_ipa_conn_id := -1;
+	/* Are we a BSC/MGW (truel) or MSC (false) */
+	var boolean g_is_bsc_mgw;
 
 	var IpaMode g_mode;
 }
@@ -47,6 +57,7 @@
 	res := IPA_CodecPort_CtrlFunct.f_IPL4_connect(IPA_PORT, remote_host, remote_port,
 						local_host, local_port, 0, { tcp:={} });
 	g_ipa_conn_id := res.connId;
+	g_is_bsc_mgw := true;
 }
 
 function f_bind(charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT {
@@ -54,6 +65,7 @@
 	res := IPA_CodecPort_CtrlFunct.f_IPL4_listen(IPA_PORT, 
 						local_host, local_port, { tcp:={} });
 	g_ipa_conn_id := res.connId;
+	g_is_bsc_mgw := false;
 }
 
 template ASP_MTP3_TRANSFERind ts_MTP3_XFER_ind(integer opc, octetstring data) := {
@@ -103,12 +115,7 @@
 
 /* transmit IPA CCM message */
 private function f_ccm_tx(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT {
-	var IPA_Send ipa_tx := {
-		connId := g_ipa_conn_id,
-		streamId := IPAC_PROTO_CCM,
-		streamIdExt := omit,
-		msg := enc_PDU_IPA_CCM(ccm)
-	}
+	var IPA_Send ipa_tx := valueof(t_IPA_Send(g_ipa_conn_id, IPAC_PROTO_CCM, enc_PDU_IPA_CCM(ccm)));
 	log("CCM Tx:", ccm);
 	IPA_PORT.send(ipa_tx);
 }
@@ -160,12 +167,8 @@
 }
 
 private function f_from_asp(ConnectionId connId, ASP_IPA_Unitdata ipa_tx) return IPA_Send {
-	var IPA_Send ret := {
-		connId := connId,
-		streamId := ipa_tx.streamId,
-		streamIdExt := ipa_tx.streamIdExt,
-		msg := ipa_tx.payload
-	}
+	var IPA_Send ret := valueof(t_IPA_Send(connId, ipa_tx.streamId, ipa_tx.payload,
+						ipa_tx.streamIdExt));
 	return ret;
 }
 
@@ -182,11 +185,24 @@
 	ScanEvents();
 }
 
+private function f_mgcp_to_user(octetstring msg) runs on IPA_Emulation_CT {
+	var charstring msg_ch := oct2char(msg);
+	if (g_is_bsc_mgw) {
+		log("============");
+		log(msg_ch);
+		IPA_MGCP_PORT.send(dec_MgcpCommand(msg_ch));
+	} else {
+		IPA_MGCP_PORT.send(dec_MgcpResponse(msg_ch));
+	}
+}
+
 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;
 	var ASP_Event asp_evt;
+	var MgcpCommand mgcp_cmd;
+	var MgcpResponse mgcp_rsp;
 
 	while (true) {
 		alt {
@@ -197,13 +213,21 @@
 				var PDU_IPA_CCM ccm := dec_PDU_IPA_CCM(ipa_rx.msg);
 				log("CCM Rx:", ccm);
 				f_ccm_rx(ccm);
-				}
-			case (IPAC_PROTO_SCCP) {
+			} case (IPAC_PROTO_SCCP) {
 				var ASP_MTP3_TRANSFERind mtp;
 				mtp := valueof(ts_MTP3_XFER_ind(0, ipa_rx.msg));
 				MTP3_SP_PORT.send(mtp);
+			} case (IPAC_PROTO_MGCP_OLD) {
+				f_mgcp_to_user(ipa_rx.msg);
+			} case (IPAC_PROTO_OSMO) {
+				select (ipa_rx.streamIdExt) {
+					case (IPAC_PROTO_EXT_MGCP) {
+						f_mgcp_to_user(ipa_rx.msg);
+					} case else {
+						IPA_SP_PORT.send(f_to_asp(ipa_rx));
+					}
 				}
-			case else {
+			} case else {
 				IPA_SP_PORT.send(f_to_asp(ipa_rx));
 				}
 			}
@@ -226,15 +250,31 @@
 
 		/* Received SCCP -> down into IPA */
 		[] MTP3_SP_PORT.receive(ASP_MTP3_TRANSFERreq: ?) -> value mtp_req {
-			var IPA_Send ipa_tx := {
-				connId := g_ipa_conn_id,
-				streamId := IPAC_PROTO_SCCP,
-				msg := mtp_req.data
-			}
+			var IPA_Send ipa_tx := valueof(t_IPA_Send(g_ipa_conn_id, IPAC_PROTO_SCCP,
+							mtp_req.data));
 			IPA_PORT.send(ipa_tx);
 		}
 
-		/* Received MISC (RSL/OML/CTRL/MGCP) -> down into IPA */
+		/* Received MGCP -> down into IPA */
+		[] IPA_MGCP_PORT.receive(MgcpCommand:?) -> value mgcp_cmd {
+			ipa_ud := {
+				streamId := IPAC_PROTO_OSMO,
+				streamIdExt := IPAC_PROTO_EXT_MGCP,
+				payload := char2oct(enc_MgcpCommand(mgcp_cmd))
+			}
+			IPA_PORT.send(f_from_asp(g_ipa_conn_id, ipa_ud));
+		}
+		[] IPA_MGCP_PORT.receive(MgcpResponse:?) -> value mgcp_rsp {
+			ipa_ud := {
+				streamId := IPAC_PROTO_OSMO,
+				streamIdExt := IPAC_PROTO_EXT_MGCP,
+				payload := char2oct(enc_MgcpResponse(mgcp_rsp))
+			}
+			IPA_PORT.send(f_from_asp(g_ipa_conn_id, ipa_ud));
+		}
+
+
+		/* Received MISC (RSL/OML/CTRL) -> down into IPA */
 		[] IPA_SP_PORT.receive(ASP_IPA_Unitdata: ?) -> value ipa_ud {
 			IPA_PORT.send(f_from_asp(g_ipa_conn_id, ipa_ud));
 		}
diff --git a/library/MGCP_Templates.ttcn b/library/MGCP_Templates.ttcn
index f78bfc7..30a5c8e 100644
--- a/library/MGCP_Templates.ttcn
+++ b/library/MGCP_Templates.ttcn
@@ -102,6 +102,16 @@
 		return cmd;
 	}
 
+	template MgcpResponse tr_DLCX_ACK := {
+		line := {
+			code := "200",
+			trans_id := ?,
+			string := "OK"
+		},
+		params:= *,
+		sdp := *
+	}
+
 	/* SDP Templates */
 	template SDP_Origin ts_SDP_origin(charstring addr, charstring session_id,
 					  charstring session_version := "1",