library/DIAMETER_Emulation: implement 'raw' mode of operation

This patch implements a new mode of operation, which allows to
have direct communication between the emulation component and
the other component connected via the 'DIAMETER_UNIT' port.
This eliminates the need to have dedicated components for each
IMSI, what is not necessarily needed in some specific cases.

Change-Id: I52e22ac70cc85be5b0436b68c77356aabc4f05e1
Related: SYS#5602
diff --git a/library/DIAMETER_Emulation.ttcn b/library/DIAMETER_Emulation.ttcn
index 220ab11..e35a87a 100644
--- a/library/DIAMETER_Emulation.ttcn
+++ b/library/DIAMETER_Emulation.ttcn
@@ -18,6 +18,10 @@
  * the DiameterOps.unitdata_cb() callback, which is registered with an argument to the
  * main() function below.
  *
+ * Alternatively, all inbound DIAMETER PDUs can be routed to a single component
+ * regardless of the IMSI.  This is called 'raw' mode and can be achieved by
+ * setting the 'raw' field in DIAMETEROps to true.
+ *
  * (C) 2019 by Harald Welte <laforge@gnumonks.org>
  * All rights reserved.
  *
@@ -94,7 +98,10 @@
 
 type record DIAMETEROps {
 	DIAMETERCreateCallback create_cb,
-	DIAMETERUnitdataCallback unitdata_cb
+	DIAMETERUnitdataCallback unitdata_cb,
+	/* If true, this parameter disables IMSI based routing, so that all incoming
+	 * PDUs get routed to a single component connected via the DIAMETER_UNIT port. */
+	boolean raw
 }
 
 type record DIAMETER_conn_parameters {
@@ -337,8 +344,16 @@
 			DIAMETER.send(t_DIAMETER_Send(g_diameter_conn_id, valueof(resp)));
 			}
 
-		/* DIAMETER from remote peer */
-		[] DIAMETER.receive(tr_DIAMETER_RecvFrom_R(?)) -> value mrf {
+		/* DIAMETER from the test suite */
+		[ops.raw] DIAMETER_UNIT.receive(PDU_DIAMETER:?) -> value msg {
+			DIAMETER.send(t_DIAMETER_Send(g_diameter_conn_id, msg));
+			}
+		/* DIAMETER from remote peer (raw mode) */
+		[ops.raw] DIAMETER.receive(tr_DIAMETER_RecvFrom_R(?)) -> value mrf {
+			DIAMETER_UNIT.send(mrf.msg);
+			}
+		/* DIAMETER from remote peer (IMSI based routing) */
+		[not ops.raw] DIAMETER.receive(tr_DIAMETER_RecvFrom_R(?)) -> value mrf {
 			imsi_t := f_DIAMETER_get_imsi(mrf.msg);
 			if (isvalue(imsi_t)) {
 				imsi := valueof(imsi_t);
diff --git a/mme/MME_Tests.ttcn b/mme/MME_Tests.ttcn
index 375a66a..3c35359 100644
--- a/mme/MME_Tests.ttcn
+++ b/mme/MME_Tests.ttcn
@@ -213,7 +213,8 @@
 friend function f_init_diameter(charstring id) runs on MTC_CT {
 	var DIAMETEROps ops := {
 		create_cb := refers(DIAMETER_Emulation.ExpectedCreateCallback),
-		unitdata_cb := refers(DiameterForwardUnitdataCallback)
+		unitdata_cb := refers(DiameterForwardUnitdataCallback),
+		raw := false /* handler mode (IMSI based routing) */
 	};
 	var DIAMETER_conn_parameters pars := {
 		remote_ip := mp_mme_ip,
diff --git a/pgw/PGW_Tests.ttcn b/pgw/PGW_Tests.ttcn
index c526fa2..75dcb83 100644
--- a/pgw/PGW_Tests.ttcn
+++ b/pgw/PGW_Tests.ttcn
@@ -115,7 +115,8 @@
 friend function f_init_diameter(charstring id) runs on PGW_Test_CT {
 	var DIAMETEROps ops := {
 		create_cb := refers(DIAMETER_Emulation.ExpectedCreateCallback),
-		unitdata_cb := refers(DiameterForwardUnitdataCallback)
+		unitdata_cb := refers(DiameterForwardUnitdataCallback),
+		raw := false /* handler mode (IMSI based routing) */
 	};
 	var DIAMETER_conn_parameters pars := {
 		remote_ip := mp_pgw_hostname,