NS_Emulation: Support multiple NS-VC within one NSE (NS-VCG)

This is something we need to simulate more complex scenarios,
particularly in the context of frame relay.

Change-Id: If1220852785853f8a5d8de183d5053ddd6ccb958
diff --git a/pcu/PCU_Tests.cfg b/pcu/PCU_Tests.cfg
index 98f8676..dd6b111 100644
--- a/pcu/PCU_Tests.cfg
+++ b/pcu/PCU_Tests.cfg
@@ -8,18 +8,22 @@
 
 [MODULE_PARAMETERS]
 SGSN_Components.mp_nsconfig := {
-	provider := {
-		ip := {
-			address_family := AF_INET,
-			local_ip := "127.0.0.1",
-			local_udp_port := 23000,
-			remote_ip := "127.0.0.1",
-			remote_udp_port := 22000
-		}
-	},
-	nsvci := 1234,
 	nsei := 1234,
-	handle_sns := false
+	handle_sns := false,
+	nsvc := {
+		{
+			provider := {
+				ip := {
+					address_family := AF_INET,
+					local_ip := "127.0.0.1",
+					local_udp_port := 23000,
+					remote_ip := "127.0.0.1",
+					remote_udp_port := 22000
+				}
+			},
+			nsvci := 1234
+		}
+	}
 }
 
 [TESTPORT_PARAMETERS]
diff --git a/pcu/PCU_Tests.ttcn b/pcu/PCU_Tests.ttcn
index 4df040e..8f424ab 100644
--- a/pcu/PCU_Tests.ttcn
+++ b/pcu/PCU_Tests.ttcn
@@ -98,11 +98,11 @@
 	ul_tbf_ext := 250 * 10, /* ms */
 	initial_cs := 2,
 	initial_mcs := 6,
-	nsvci := { mp_nsconfig.nsvci, 0 },
-	local_port := { mp_nsconfig.provider.ip.remote_udp_port, 0 },
-	remote_port := { mp_nsconfig.provider.ip.local_udp_port, 0 },
+	nsvci := { mp_nsconfig.nsvc[0].nsvci, 0 },
+	local_port := { mp_nsconfig.nsvc[0].provider.ip.remote_udp_port, 0 },
+	remote_port := { mp_nsconfig.nsvc[0].provider.ip.local_udp_port, 0 },
 	remote_addr := f_PCUIF_ver_INFO_RemoteAddr(
-		f_PCUIF_AF2addr_type(mp_nsconfig.provider.ip.address_family), mp_nsconfig.provider.ip.local_ip)
+		f_PCUIF_AF2addr_type(mp_nsconfig.nsvc[0].provider.ip.address_family), mp_nsconfig.nsvc[0].provider.ip.local_ip)
 }
 
 type record lqual_range {
diff --git a/pcu/PCU_Tests_NS.ttcn b/pcu/PCU_Tests_NS.ttcn
index 4db78d8..e782b6e 100644
--- a/pcu/PCU_Tests_NS.ttcn
+++ b/pcu/PCU_Tests_NS.ttcn
@@ -98,7 +98,7 @@
 	var integer i;
 	for (i := 0; i < 3; i := i+1) {
 		NSCP[0].receive(t_NS_RecvFrom(tr_NS_RESET(NS_CAUSE_OM_INTERVENTION,
-							g_nsconfig[0].nsvci, g_nsconfig[0].nsei)));
+							g_nsconfig[0].nsvc[0].nsvci, g_nsconfig[0].nsei)));
 	}
 
 	/* Expect inbound NS-RESET procedure */
diff --git a/pcu/PCU_Tests_SNS.cfg b/pcu/PCU_Tests_SNS.cfg
index 6a64626..e5a08fe 100644
--- a/pcu/PCU_Tests_SNS.cfg
+++ b/pcu/PCU_Tests_SNS.cfg
@@ -8,17 +8,21 @@
 
 [MODULE_PARAMETERS]
 SGSN_Components.mp_nsconfig := {
-	provider := {
-		ip := {
-			address_family := AF_INET,
-			local_ip := "127.0.0.1",
-			local_udp_port := 23000,
-			remote_ip := "127.0.0.1",
-			remote_udp_port := 22000
+	nsei := 1234,
+	nsvc := {
+		{
+			provider := {
+				ip := {
+					address_family := AF_INET,
+					local_ip := "127.0.0.1",
+					local_udp_port := 23000,
+					remote_ip := "127.0.0.1",
+					remote_udp_port := 22000
+				}
+			},
+			nsvci := 1234
 		}
-	},
-	nsvci := 1234,
-	nsei := 1234
+	}
 }
 PCUIF_Types.mp_pcuif_version := 10
 
diff --git a/pcu/PCU_Tests_SNS.ttcn b/pcu/PCU_Tests_SNS.ttcn
index 86b83c2..cd0cc67 100644
--- a/pcu/PCU_Tests_SNS.ttcn
+++ b/pcu/PCU_Tests_SNS.ttcn
@@ -14,6 +14,7 @@
 import from PCU_Tests_NS all;
 import from SGSN_Components all;
 import from Osmocom_Gb_Types all;
+import from NS_Emulation all;
 import from NS_CodecPort all;
 import from NS_Types all;
 import from RAW_NS all;
@@ -27,8 +28,9 @@
 runs on RAW_NS_CT {
 	log("f_incoming_sns_size(idx=", idx, ")");
 	var PDU_NS rx;
+	var NSVCConfiguration nsvc_cfg := g_nsconfig[idx].nsvc[0];
 
-	if (mp_nsconfig.provider.ip.address_family == AF_INET) {
+	if (nsvc_cfg.provider.ip.address_family == AF_INET) {
 		/* expect one single SNS-SIZE with RESET flag; 4x v4 EP; no v6 EP */
 		rx := f_ns_exp(tr_SNS_SIZE(g_nsconfig[idx].nsei, rst_flag := true, max_nsvcs := 8,
 					   num_v4 := 4, num_v6 := omit), idx);
@@ -45,7 +47,9 @@
 runs on RAW_NS_CT {
 	log("f_outgoing_sns_size(idx=", idx, ")");
 	var PDU_NS rx;
-	if (mp_nsconfig.provider.ip.address_family == AF_INET) {
+	var NSVCConfiguration nsvc_cfg := g_nsconfig[idx].nsvc[0];
+
+	if (nsvc_cfg.provider.ip.address_family == AF_INET) {
 		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_SIZE(g_nsconfig[idx].nsei, rst_flag := true, max_nsvcs := 1,
 								num_v4 := 1, num_v6 := omit)
 					));
@@ -63,17 +67,17 @@
 runs on RAW_NS_CT {
 	log("f_incoming_sns_config(idx=", idx, ")");
 	var PDU_NS rx;
+	var NSVCConfiguration nsvc_cfg := g_nsconfig[idx].nsvc[0];
 
-	if (mp_nsconfig.provider.ip.address_family == AF_INET) {
-		var template IP4_Elements v4_elem := { tr_SNS_IPv4(mp_nsconfig.provider.ip.remote_ip,
-								   mp_nsconfig.provider.ip.remote_udp_port) };
+	if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+		var template IP4_Elements v4_elem := { tr_SNS_IPv4(nsvc_cfg.provider.ip.remote_ip,
+								   nsvc_cfg.provider.ip.remote_udp_port) };
 		rx := f_ns_exp(tr_SNS_CONFIG(g_nsconfig[idx].nsei, end_flag := true, v4 := v4_elem), idx);
 	} else {
-		var template IP6_Elements v6_elem := { tr_SNS_IPv6(mp_nsconfig.provider.ip.remote_ip,
-								   mp_nsconfig.provider.ip.remote_udp_port) };
+		var template IP6_Elements v6_elem := { tr_SNS_IPv6(nsvc_cfg.provider.ip.remote_ip,
+								   nsvc_cfg.provider.ip.remote_udp_port) };
 		rx := f_ns_exp(tr_SNS_CONFIG(g_nsconfig[idx].nsei, end_flag := true, v6 := v6_elem), idx);
 	}
-
 	NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG_ACK(g_nsconfig[idx].nsei, cause)));
 }
 
@@ -82,13 +86,15 @@
 runs on RAW_NS_CT {
 	log("f_outgoing_sns_config(idx=", idx, ")");
 	var PDU_NS rx;
-	if (mp_nsconfig.provider.ip.address_family == AF_INET) {
-		var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig[idx].provider.ip.local_ip,
-								     g_nsconfig[idx].provider.ip.local_udp_port) }
+	var NSVCConfiguration nsvc_cfg := g_nsconfig[idx].nsvc[0];
+
+	if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+		var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(nsvc_cfg.provider.ip.local_ip,
+								     nsvc_cfg.provider.ip.local_udp_port) }
 		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG(g_nsconfig[idx].nsei, true, v4)));
 	} else {
-		var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(g_nsconfig[idx].provider.ip.local_ip,
-								     g_nsconfig[idx].provider.ip.local_udp_port) }
+		var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(nsvc_cfg.provider.ip.local_ip,
+								     nsvc_cfg.provider.ip.local_udp_port) }
 		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG(g_nsconfig[idx].nsei, true, omit, v6)));
 	}
 	rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig[idx].nsei, cause), idx);
@@ -99,17 +105,18 @@
 runs on RAW_NS_CT {
 	log("f_outgoing_sns_config_1c1u(idx=", idx, ")");
 	var PDU_NS rx;
-	if (mp_nsconfig.provider.ip.address_family == AF_INET) {
-		var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig[0].provider.ip.local_ip,
-								     g_nsconfig[0].provider.ip.local_udp_port, 1, 0),
-							 ts_SNS_IPv4(g_nsconfig[1].provider.ip.local_ip,
-								     g_nsconfig[1].provider.ip.local_udp_port, 0, 1) };
+
+	if (mp_nsconfig.nsvc[0].provider.ip.address_family == AF_INET) {
+		var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig[0].nsvc[0].provider.ip.local_ip,
+								     g_nsconfig[0].nsvc[0].provider.ip.local_udp_port, 1, 0),
+							 ts_SNS_IPv4(g_nsconfig[1].nsvc[0].provider.ip.local_ip,
+								     g_nsconfig[1].nsvc[0].provider.ip.local_udp_port, 0, 1) };
 		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG(g_nsconfig[idx].nsei, true, v4)));
 	} else {
-		var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(g_nsconfig[0].provider.ip.local_ip,
-								     g_nsconfig[0].provider.ip.local_udp_port, 1, 0),
-							 ts_SNS_IPv6(g_nsconfig[1].provider.ip.local_ip,
-								     g_nsconfig[1].provider.ip.local_udp_port, 0, 1) };
+		var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(g_nsconfig[0].nsvc[0].provider.ip.local_ip,
+								     g_nsconfig[0].nsvc[0].provider.ip.local_udp_port, 1, 0),
+							 ts_SNS_IPv6(g_nsconfig[1].nsvc[0].provider.ip.local_ip,
+								     g_nsconfig[1].nsvc[0].provider.ip.local_udp_port, 0, 1) };
 		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG(g_nsconfig[idx].nsei, true, omit, v6)));
 	}
 	rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig[idx].nsei, cause), idx);
@@ -120,17 +127,17 @@
 runs on RAW_NS_CT {
 	log("f_outgoing_sns_config_1c1u_separate(idx=", idx, ")");
 	var PDU_NS rx;
-	if (mp_nsconfig.provider.ip.address_family == AF_INET) {
-		var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig[1].provider.ip.local_ip,
-								     g_nsconfig[1].provider.ip.local_udp_port, 1, 0),
-							 ts_SNS_IPv4(g_nsconfig[2].provider.ip.local_ip,
-								     g_nsconfig[2].provider.ip.local_udp_port, 0, 1) };
+	if (mp_nsconfig.nsvc[0].provider.ip.address_family == AF_INET) {
+		var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig[1].nsvc[0].provider.ip.local_ip,
+								     g_nsconfig[1].nsvc[0].provider.ip.local_udp_port, 1, 0),
+							 ts_SNS_IPv4(g_nsconfig[2].nsvc[0].provider.ip.local_ip,
+								     g_nsconfig[2].nsvc[0].provider.ip.local_udp_port, 0, 1) };
 		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG(g_nsconfig[idx].nsei, true, v4)));
 	} else {
-		var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(g_nsconfig[1].provider.ip.local_ip,
-								     g_nsconfig[1].provider.ip.local_udp_port, 1, 0),
-							 ts_SNS_IPv6(g_nsconfig[2].provider.ip.local_ip,
-								     g_nsconfig[2].provider.ip.local_udp_port, 0, 1) };
+		var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(g_nsconfig[1].nsvc[0].provider.ip.local_ip,
+								     g_nsconfig[1].nsvc[0].provider.ip.local_udp_port, 1, 0),
+							 ts_SNS_IPv6(g_nsconfig[2].nsvc[0].provider.ip.local_ip,
+								     g_nsconfig[2].nsvc[0].provider.ip.local_udp_port, 0, 1) };
 		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG(g_nsconfig[idx].nsei, true, omit, v6)));
 	}
 	rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig[idx].nsei, cause), idx);
@@ -140,15 +147,16 @@
 runs on RAW_NS_CT {
 	log("f_outgoing_sns_add(idx_add=", idx_add, ")");
 	var PDU_NS rx;
-	if (mp_nsconfig.provider.ip.address_family == AF_INET) {
-		var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig[idx_add].provider.ip.local_ip,
-								     g_nsconfig[idx_add].provider.ip.local_udp_port,
+	var NSVCConfiguration nsvc_cfg := g_nsconfig[idx].nsvc[0];
+	if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+		var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(nsvc_cfg.provider.ip.local_ip,
+								     nsvc_cfg.provider.ip.local_udp_port,
 								     w_sig, w_user) };
 		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_ADD(g_nsconfig[idx].nsei, 23, v4)));
 		rx := f_ns_exp(tr_SNS_ACK(g_nsconfig[idx].nsei, 23, omit, v4));
 	} else {
-		var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(g_nsconfig[idx_add].provider.ip.local_ip,
-								     g_nsconfig[idx_add].provider.ip.local_udp_port,
+		var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(nsvc_cfg.provider.ip.local_ip,
+								     nsvc_cfg.provider.ip.local_udp_port,
 								     w_sig, w_user) };
 		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_ADD(g_nsconfig[idx].nsei, 23, omit, v6)));
 		rx := f_ns_exp(tr_SNS_ACK(g_nsconfig[idx].nsei, 23, omit, omit, v6));
@@ -159,15 +167,16 @@
 runs on RAW_NS_CT {
 	log("f_outgoing_sns_del(idx_del=", idx_del, ")");
 	var PDU_NS rx;
-	if (mp_nsconfig.provider.ip.address_family == AF_INET) {
-		var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig[idx_del].provider.ip.local_ip,
-								     g_nsconfig[idx_del].provider.ip.local_udp_port,
+	var NSVCConfiguration nsvc_cfg := g_nsconfig[idx_del].nsvc[0];
+	if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+		var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(nsvc_cfg.provider.ip.local_ip,
+								     nsvc_cfg.provider.ip.local_udp_port,
 								     w_sig, w_user) };
 		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_DEL(g_nsconfig[idx].nsei, 24, omit, v4)));
 		rx := f_ns_exp(tr_SNS_ACK(g_nsconfig[idx].nsei, 24, omit, v4));
 	} else {
-		var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(g_nsconfig[idx_del].provider.ip.local_ip,
-								     g_nsconfig[idx_del].provider.ip.local_udp_port,
+		var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(nsvc_cfg.provider.ip.local_ip,
+								     nsvc_cfg.provider.ip.local_udp_port,
 								     w_sig, w_user) };
 		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_DEL(g_nsconfig[idx].nsei, 24, omit, omit, v6)));
 		rx := f_ns_exp(tr_SNS_ACK(g_nsconfig[idx].nsei, 24, omit, omit, v6));
@@ -178,15 +187,16 @@
 runs on RAW_NS_CT {
 	log("f_outgoing_sns_chg_weight(idx_chg=", idx_chg, ")");
 	var PDU_NS rx;
-	if (mp_nsconfig.provider.ip.address_family == AF_INET) {
-		var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig[idx_chg].provider.ip.local_ip,
-								     g_nsconfig[idx_chg].provider.ip.local_udp_port,
+	var NSVCConfiguration nsvc_cfg := g_nsconfig[idx_chg].nsvc[0];
+	if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+		var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(nsvc_cfg.provider.ip.local_ip,
+								     nsvc_cfg.provider.ip.local_udp_port,
 								     w_sig, w_user) };
 		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CHG_WEIGHT(g_nsconfig[idx].nsei, 25, v4)));
 		rx := f_ns_exp(tr_SNS_ACK(g_nsconfig[idx].nsei, 25, omit, v4));
 	} else {
-		var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(g_nsconfig[idx_chg].provider.ip.local_ip,
-								     g_nsconfig[idx_chg].provider.ip.local_udp_port,
+		var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(nsvc_cfg.provider.ip.local_ip,
+								     nsvc_cfg.provider.ip.local_udp_port,
 								     w_sig, w_user) };
 		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CHG_WEIGHT(g_nsconfig[idx].nsei, 25, omit, v6)));
 		rx := f_ns_exp(tr_SNS_ACK(g_nsconfig[idx].nsei, 25, omit, omit, v6));
diff --git a/pcu/PCU_Tests_SNSv6.cfg b/pcu/PCU_Tests_SNSv6.cfg
index af986bf..cae9a75 100644
--- a/pcu/PCU_Tests_SNSv6.cfg
+++ b/pcu/PCU_Tests_SNSv6.cfg
@@ -8,17 +8,21 @@
 
 [MODULE_PARAMETERS]
 SGSN_Components.mp_nsconfig := {
-	provider := {
-		ip := {
-			address_family := AF_INET6,
-			local_ip := "::1",
-			local_udp_port := 23000,
-			remote_ip := "::1",
-			remote_udp_port := 22000,
+	nsei := 1234,
+	nsvc : {
+		{
+			provider := {
+				ip := {
+					address_family := AF_INET6,
+					local_ip := "::1",
+					local_udp_port := 23000,
+					remote_ip := "::1",
+					remote_udp_port := 22000,
+				}
+			},
+			nsvci := 1234
 		}
-	},
-	nsvci := 1234,
-	nsei := 1234
+	}
 }
 PCUIF_Types.mp_pcuif_version := 10
 
diff --git a/pcu/SGSN_Components.ttcn b/pcu/SGSN_Components.ttcn
index 2f1fa75..5f05595 100644
--- a/pcu/SGSN_Components.ttcn
+++ b/pcu/SGSN_Components.ttcn
@@ -39,19 +39,23 @@
 	};
 
 	NSConfiguration mp_nsconfig := {
-		provider := {
-			ip := {
-				address_family := AF_INET,
-				local_udp_port := 23000,
-				local_ip := "127.0.0.1",
-				remote_udp_port := 21000,
-				remote_ip := "127.0.0.1"
-			}
-		},
-		nsvci := 0,
 		nsei := 2342,
 		role_sgsn := true,
-		handle_sns := true
+		handle_sns := true,
+		nsvc := {
+			{
+				provider := {
+					ip := {
+						address_family := AF_INET,
+						local_udp_port := 23000,
+						local_ip := "127.0.0.1",
+						remote_udp_port := 21000,
+						remote_ip := "127.0.0.1"
+					}
+				},
+				nsvci := 0
+			}
+		}
 	};
 }