RAW_NS: rework NS connection to use NS_Provider

Previous RAW_NS only supported NS over UDP because
it handled the UDP connection on it's own.
Because of this there was no cleanup function for the tests
because no virtual component were started.
Using the new NS_Provider allows to use the same tests over
UDP and FR with no changes.

Change-Id: I8a3b6c72798a75f434f54229fdbfc802cd13967e
diff --git a/pcu/PCU_Tests.cfg b/pcu/PCU_Tests.cfg
index dd6b111..13bedec 100644
--- a/pcu/PCU_Tests.cfg
+++ b/pcu/PCU_Tests.cfg
@@ -22,6 +22,30 @@
 				}
 			},
 			nsvci := 1234
+		},
+		{
+			provider := {
+				ip := {
+					address_family := AF_INET,
+					local_ip := "127.0.0.1",
+					local_udp_port := 23001,
+					remote_ip := "127.0.0.1",
+					remote_udp_port := 22000
+				}
+			},
+			nsvci := 1234
+		},
+		{
+			provider := {
+				ip := {
+					address_family := AF_INET,
+					local_ip := "127.0.0.1",
+					local_udp_port := 23002,
+					remote_ip := "127.0.0.1",
+					remote_udp_port := 22000
+				}
+			},
+			nsvci := 1234
 		}
 	}
 }
diff --git a/pcu/PCU_Tests_NS.ttcn b/pcu/PCU_Tests_NS.ttcn
index e782b6e..9cf37b5 100644
--- a/pcu/PCU_Tests_NS.ttcn
+++ b/pcu/PCU_Tests_NS.ttcn
@@ -15,12 +15,9 @@
 import from PCU_Tests all;
 import from SGSN_Components all;
 import from Osmocom_Gb_Types all;
-import from NS_CodecPort all;
 import from NS_Types all;
 import from BSSGP_Types all;
 import from UD_Types all;
-import from NS_CodecPort all;
-import from NS_CodecPort_CtrlFunct all;
 import from NS_Emulation all;
 import from Native_Functions all;
 import from IPL4asp_Types all;
@@ -70,7 +67,7 @@
 	timer T := tout;
 	T.start;
 	alt {
-	[] NSCP[idx].receive(t_NS_RecvFrom(ns)) {
+	[] NSCP[idx].receive(ns) {
 		setverdict(fail, "NS-ALIVE from unconfigured (possibly initial) endpoint");
 		}
 	[] T.timeout {
@@ -88,6 +85,7 @@
 	/* Expect inbound NS-RESET procedure */
 	as_rx_ns_reset_ack(oneshot := true);
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 /* ensure NS-RESET are re-transmitted */
@@ -97,13 +95,14 @@
 
 	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].nsvc[0].nsvci, g_nsconfig[0].nsei)));
+		NSCP[0].receive(tr_NS_RESET(NS_CAUSE_OM_INTERVENTION,
+					    g_nsconfig.nsvc[0].nsvci, g_nsconfig.nsei));
 	}
 
 	/* Expect inbound NS-RESET procedure */
 	as_rx_ns_reset_ack(oneshot := true);
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 /* test the inbound NS-ALIVE procedure after NS-RESET */
@@ -116,9 +115,10 @@
 
 	alt {
 	/* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
-	[] NSCP[0].receive(t_NS_RecvFrom(t_NS_ALIVE)) { setverdict(pass); };
-	[] NSCP[0].receive(t_NS_RecvFrom(t_NS_UNBLOCK)) { repeat; }
+	[] NSCP[0].receive(t_NS_ALIVE) { setverdict(pass); };
+	[] NSCP[0].receive(t_NS_UNBLOCK) { repeat; }
 	}
+	f_clean_ns_codec();
 }
 
 /* Test for NS-RESET after NS-ALIVE timeout */
@@ -132,15 +132,17 @@
 	/* wait for at least one NS-ALIVE */
 	alt {
 	[] as_rx_alive_tx_ack(oneshot := true) { };
-	[] NSCP[0].receive(t_NS_RecvFrom(t_NS_UNBLOCK)) { repeat; }
+	[] NSCP[0].receive(t_NS_UNBLOCK) { repeat; }
 	}
 
 	/* wait for NS-RESET to re-appear, ignoring any NS-ALIVE until then */
 	alt {
 	[] as_rx_ns_reset_ack(oneshot := true) { setverdict(pass); }
-	[] NSCP[0].receive(t_NS_RecvFrom(t_NS_ALIVE)) { repeat; }
-	[] NSCP[0].receive(t_NS_RecvFrom(t_NS_UNBLOCK)) { repeat; }
+	[] NSCP[0].receive(t_NS_ALIVE) { repeat; }
+	[] NSCP[0].receive(t_NS_UNBLOCK) { repeat; }
 	}
+
+	f_clean_ns_codec();
 }
 
 /* test for NS-RESET/NS-ALIVE/NS-UNBLOCK */
@@ -156,6 +158,7 @@
 
 	as_rx_ns_unblock_ack(oneshot := true);
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 /* test for NS-UNBLOCK re-transmissions */
@@ -170,11 +173,12 @@
 	activate(as_rx_alive_tx_ack());
 
 	/* wait for first NS-UNBLOCK, don't respond */
-	NSCP[0].receive(t_NS_RecvFrom(t_NS_UNBLOCK));
+	NSCP[0].receive(t_NS_UNBLOCK);
 
 	/* wait for re-transmission of NS-UNBLOCK */
 	as_rx_ns_unblock_ack(oneshot := true);
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 /* full bring-up of the Gb link for NS and BSSGP layer up to BVC-FC */
@@ -205,6 +209,7 @@
 	as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true);
 	activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci));
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 /* test outbound (SGSN-originated) NS-BLOCK procedure */
@@ -224,6 +229,7 @@
 
 	f_outgoing_ns_block(NS_CAUSE_EQUIPMENT_FAILURE);
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 
diff --git a/pcu/PCU_Tests_SNS.cfg b/pcu/PCU_Tests_SNS.cfg
index e5a08fe..ab589c5 100644
--- a/pcu/PCU_Tests_SNS.cfg
+++ b/pcu/PCU_Tests_SNS.cfg
@@ -21,6 +21,30 @@
 				}
 			},
 			nsvci := 1234
+		},
+		{
+			provider := {
+				ip := {
+					address_family := AF_INET,
+					local_ip := "127.0.0.1",
+					local_udp_port := 23001,
+					remote_ip := "127.0.0.1",
+					remote_udp_port := 22000
+				}
+			},
+			nsvci := 1234
+		},
+		{
+			provider := {
+				ip := {
+					address_family := AF_INET,
+					local_ip := "127.0.0.1",
+					local_udp_port := 23002,
+					remote_ip := "127.0.0.1",
+					remote_udp_port := 22000
+				}
+			},
+			nsvci := 1234
 		}
 	}
 }
diff --git a/pcu/PCU_Tests_SNS.ttcn b/pcu/PCU_Tests_SNS.ttcn
index ea78761..4fca26e 100644
--- a/pcu/PCU_Tests_SNS.ttcn
+++ b/pcu/PCU_Tests_SNS.ttcn
@@ -15,7 +15,6 @@
 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;
 
@@ -28,18 +27,18 @@
 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];
+	var NSVCConfiguration nsvc_cfg := g_nsconfig.nsvc[idx];
 
 	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,
+		rx := f_ns_exp(tr_SNS_SIZE(g_nsconfig.nsei, rst_flag := true, max_nsvcs := 8,
 					   num_v4 := 4, num_v6 := omit), idx);
 	} else {
 		/* expect one single SNS-SIZE with RESET flag; no v4 EP; 4x v6 EP */
-		rx := f_ns_exp(tr_SNS_SIZE(g_nsconfig[idx].nsei, rst_flag := true, max_nsvcs := 8,
+		rx := f_ns_exp(tr_SNS_SIZE(g_nsconfig.nsei, rst_flag := true, max_nsvcs := 8,
 					   num_v4 := omit, num_v6 := 4), idx);
 	}
-	NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_SIZE_ACK(g_nsconfig[idx].nsei, cause)));
+	NSCP[idx].send(ts_SNS_SIZE_ACK(g_nsconfig.nsei, cause));
 }
 
 /* perform outbound SNS-SIZE procedure */
@@ -47,19 +46,19 @@
 runs on RAW_NS_CT {
 	log("f_outgoing_sns_size(idx=", idx, ")");
 	var PDU_NS rx;
-	var NSVCConfiguration nsvc_cfg := g_nsconfig[idx].nsvc[0];
+	var NSVCConfiguration nsvc_cfg := g_nsconfig.nsvc[idx];
 
 	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,
+		NSCP[idx].send(ts_SNS_SIZE(g_nsconfig.nsei, rst_flag := true, max_nsvcs := 1,
 								num_v4 := 1, num_v6 := omit)
-					));
+					);
 	} else {
-		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_SIZE(g_nsconfig[idx].nsei, rst_flag := true, max_nsvcs := 1,
+		NSCP[idx].send(ts_SNS_SIZE(g_nsconfig.nsei, rst_flag := true, max_nsvcs := 1,
 								num_v4 := omit, num_v6 := 1)
-					));
+					);
 	}
 	/* expect one single SNS-SIZE with RESET flag; 4x v4 EP; no v6 EP */
-	rx := f_ns_exp(tr_SNS_SIZE_ACK(g_nsconfig[idx].nsei, cause), idx);
+	rx := f_ns_exp(tr_SNS_SIZE_ACK(g_nsconfig.nsei, cause), idx);
 }
 
 /* perform inbound SNS-CONFIG procedure */
@@ -67,18 +66,18 @@
 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];
+	var NSVCConfiguration nsvc_cfg := g_nsconfig.nsvc[idx];
 
 	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);
+		rx := f_ns_exp(tr_SNS_CONFIG(g_nsconfig.nsei, end_flag := true, v4 := v4_elem), idx);
 	} else {
 		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);
+		rx := f_ns_exp(tr_SNS_CONFIG(g_nsconfig.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)));
+	NSCP[idx].send(ts_SNS_CONFIG_ACK(g_nsconfig.nsei, cause));
 }
 
 /* perform outbound SNS-CONFIG procedure */
@@ -86,18 +85,18 @@
 runs on RAW_NS_CT {
 	log("f_outgoing_sns_config(idx=", idx, ")");
 	var PDU_NS rx;
-	var NSVCConfiguration nsvc_cfg := g_nsconfig[idx].nsvc[0];
+	var NSVCConfiguration nsvc_cfg := g_nsconfig.nsvc[idx];
 
 	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)));
+		NSCP[idx].send(ts_SNS_CONFIG(g_nsconfig.nsei, true, v4));
 	} else {
 		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)));
+		NSCP[idx].send(ts_SNS_CONFIG(g_nsconfig.nsei, true, omit, v6));
 	}
-	rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig[idx].nsei, cause), idx);
+	rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig.nsei, cause), idx);
 }
 
 /* perform outbound SNS-CONFIG procedure (separate endpoints: 1 for control, 1 for user */
@@ -107,19 +106,19 @@
 	var PDU_NS rx;
 
 	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)));
+		var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig.nsvc[0].provider.ip.local_ip,
+								     g_nsconfig.nsvc[0].provider.ip.local_udp_port, 1, 0),
+							 ts_SNS_IPv4(g_nsconfig.nsvc[1].provider.ip.local_ip,
+								     g_nsconfig.nsvc[1].provider.ip.local_udp_port, 0, 1) };
+		NSCP[idx].send(ts_SNS_CONFIG(g_nsconfig.nsei, true, v4));
 	} else {
-		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)));
+		var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(g_nsconfig.nsvc[0].provider.ip.local_ip,
+								     g_nsconfig.nsvc[0].provider.ip.local_udp_port, 1, 0),
+							 ts_SNS_IPv6(g_nsconfig.nsvc[1].provider.ip.local_ip,
+								     g_nsconfig.nsvc[1].provider.ip.local_udp_port, 0, 1) };
+		NSCP[idx].send(ts_SNS_CONFIG(g_nsconfig.nsei, true, omit, v6));
 	}
-	rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig[idx].nsei, cause), idx);
+	rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig.nsei, cause), idx);
 }
 
 /* perform outbound SNS-CONFIG procedure (separate endpoints: 1 for control, 1 for user */
@@ -128,38 +127,38 @@
 	log("f_outgoing_sns_config_1c1u_separate(idx=", idx, ")");
 	var PDU_NS rx;
 	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)));
+		var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig.nsvc[1].provider.ip.local_ip,
+								     g_nsconfig.nsvc[1].provider.ip.local_udp_port, 1, 0),
+							 ts_SNS_IPv4(g_nsconfig.nsvc[2].provider.ip.local_ip,
+								     g_nsconfig.nsvc[2].provider.ip.local_udp_port, 0, 1) };
+		NSCP[idx].send(ts_SNS_CONFIG(g_nsconfig.nsei, true, v4));
 	} else {
-		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)));
+		var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(g_nsconfig.nsvc[1].provider.ip.local_ip,
+								     g_nsconfig.nsvc[1].provider.ip.local_udp_port, 1, 0),
+							 ts_SNS_IPv6(g_nsconfig.nsvc[2].provider.ip.local_ip,
+								     g_nsconfig.nsvc[2].provider.ip.local_udp_port, 0, 1) };
+		NSCP[idx].send(ts_SNS_CONFIG(g_nsconfig.nsei, true, omit, v6));
 	}
-	rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig[idx].nsei, cause), idx);
+	rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig.nsei, cause), idx);
 }
 
 function f_outgoing_sns_add(integer idx_add, uint8_t w_sig := 1, uint8_t w_user := 1, integer idx := 0, template (omit) NsCause cause := omit)
 runs on RAW_NS_CT {
 	log("f_outgoing_sns_add(idx_add=", idx_add, ")");
 	var PDU_NS rx;
-	var NSVCConfiguration nsvc_cfg := g_nsconfig[idx_add].nsvc[0];
+	var NSVCConfiguration nsvc_cfg := g_nsconfig.nsvc[idx_add];
 	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, cause, v4));
+		NSCP[idx].send(ts_SNS_ADD(g_nsconfig.nsei, 23, v4));
+		rx := f_ns_exp(tr_SNS_ACK(g_nsconfig.nsei, 23, cause, v4));
 	} else {
 		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, cause, omit, v6));
+		NSCP[idx].send(ts_SNS_ADD(g_nsconfig.nsei, 23, omit, v6));
+		rx := f_ns_exp(tr_SNS_ACK(g_nsconfig.nsei, 23, cause, omit, v6));
 	}
 }
 
@@ -167,19 +166,19 @@
 runs on RAW_NS_CT {
 	log("f_outgoing_sns_del(idx_del=", idx_del, ")");
 	var PDU_NS rx;
-	var NSVCConfiguration nsvc_cfg := g_nsconfig[idx_del].nsvc[0];
+	var NSVCConfiguration nsvc_cfg := g_nsconfig.nsvc[idx_del];
 	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));
+		NSCP[idx].send(ts_SNS_DEL(g_nsconfig.nsei, 24, omit, v4));
+		rx := f_ns_exp(tr_SNS_ACK(g_nsconfig.nsei, 24, omit, v4));
 	} else {
 		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));
+		NSCP[idx].send(ts_SNS_DEL(g_nsconfig.nsei, 24, omit, omit, v6));
+		rx := f_ns_exp(tr_SNS_ACK(g_nsconfig.nsei, 24, omit, omit, v6));
 	}
 }
 
@@ -187,19 +186,19 @@
 runs on RAW_NS_CT {
 	log("f_outgoing_sns_chg_weight(idx_chg=", idx_chg, ")");
 	var PDU_NS rx;
-	var NSVCConfiguration nsvc_cfg := g_nsconfig[idx_chg].nsvc[0];
+	var NSVCConfiguration nsvc_cfg := g_nsconfig.nsvc[idx_chg];
 	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));
+		NSCP[idx].send(ts_SNS_CHG_WEIGHT(g_nsconfig.nsei, 25, v4));
+		rx := f_ns_exp(tr_SNS_ACK(g_nsconfig.nsei, 25, omit, v4));
 	} else {
 		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));
+		NSCP[idx].send(ts_SNS_CHG_WEIGHT(g_nsconfig.nsei, 25, omit, v6));
+		rx := f_ns_exp(tr_SNS_ACK(g_nsconfig.nsei, 25, omit, omit, v6));
 	}
 }
 
@@ -214,6 +213,7 @@
 	f_incoming_sns_size();
 	f_sleep(1.0);
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 /* PCU-originated SNS-SIZE: NACK from our side */
@@ -225,6 +225,7 @@
 	/* FIXME: ensure we get re-transmitted SNS-SIZE attempts */
 	f_sleep(10.0);
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 /* PCU-originated SNS-CONFIG: successful case */
@@ -235,6 +236,7 @@
 	f_incoming_sns_config();
 	f_sleep(1.0);
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 /* PCU-originated SNS-CONFIG: successful case */
@@ -246,6 +248,7 @@
 	/* FIXME: ensure we get re-transmitted SNS-CONFIG attempts */
 	f_sleep(10.0);
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 
@@ -272,6 +275,7 @@
 	as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true);
 	activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci));
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 private function f_sns_bringup_1c1u(boolean sgsn_originated_reset := false) runs on RAW_Test_CT {
@@ -327,6 +331,7 @@
 testcase TC_sns_1c1u() runs on RAW_Test_CT {
 	f_sns_bringup_1c1u();
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 private function f_sns_bringup_1c1u_separate(boolean sgsn_originated_reset := false) runs on RAW_Test_CT {
@@ -387,6 +392,7 @@
 testcase TC_sns_1c1u_separate() runs on RAW_Test_CT {
 	f_sns_bringup_1c1u_separate();
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 /* Test full IP-SNS bring-up with two NS-VCs, one sig-only and one user-only and use
@@ -394,6 +400,7 @@
 testcase TC_sns_1c1u_so_bvc_reset() runs on RAW_Test_CT {
 	f_sns_bringup_1c1u_separate(sgsn_originated_reset := true);
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 /* Transmit BVC-RESET before NS-ALIVE of PCU was ACKed: expect no response */
@@ -420,6 +427,7 @@
 	/* Transmit BVC-RESET and expect no ACK*/
 	f_tx_bvc_reset_rx_ack(0, omit, omit, idx := 1, exp_ack := false);
 	f_tx_bvc_reset_rx_ack(mp_gb_cfg.bvc[0].bvci, omit, mp_gb_cfg.bvc[0].cell_id, idx := 1, exp_ack := false);
+	f_clean_ns_codec();
 }
 
 /* Test adding new IP endpoints at runtime */
@@ -437,6 +445,7 @@
 
 	f_outgoing_ns_alive(2);
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 /* Test adding an already present IP endpoint at runtime */
@@ -445,6 +454,7 @@
 
 	f_outgoing_sns_add(idx_add := 0, w_sig := 0, w_user := 1, idx := 0, cause := NS_CAUSE_PROTOCOL_ERROR_UNSPEIFIED);
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 /* Test deleting IP endpoints at runtime */
@@ -454,6 +464,7 @@
 	f_outgoing_sns_del(idx_del := 1, w_sig := 0, w_user := 1, idx := 0);
 	/* FIXME: ensure we don't receive anything on just-deleted NS-VC anymore */
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 /* Test changing weights at runtime */
@@ -463,6 +474,7 @@
 	/* change w_user from 1 to 200 */
 	f_outgoing_sns_chg_weight(idx_chg := 1, w_sig := 0, w_user := 200, idx := 0);
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 import from PCUIF_Types all;
@@ -485,6 +497,7 @@
 			       tr_PCUIF_DATA_REQ(bts_nr:=0, trx_nr:=0, ts_nr:=0, block_nr:=?, fn:=?,
 						 sapi:=PCU_IF_SAPI_AGCH, data:=?)));
 	setverdict(pass);
+	f_clean_ns_codec();
 }
 
 
diff --git a/pcu/SGSN_Components.ttcn b/pcu/SGSN_Components.ttcn
index 18f3992..08d9231 100644
--- a/pcu/SGSN_Components.ttcn
+++ b/pcu/SGSN_Components.ttcn
@@ -55,6 +55,30 @@
 					}
 				},
 				nsvci := 0
+			},
+			{
+				provider := {
+					ip := {
+						address_family := AF_INET,
+						local_udp_port := 23001,
+						local_ip := "127.0.0.1",
+						remote_udp_port := 21000,
+						remote_ip := "127.0.0.1"
+					}
+				},
+				nsvci := 0
+			},
+			{
+				provider := {
+					ip := {
+						address_family := AF_INET,
+						local_udp_port := 23002,
+						local_ip := "127.0.0.1",
+						remote_udp_port := 21000,
+						remote_ip := "127.0.0.1"
+					}
+				},
+				nsvci := 0
 			}
 		}
 	};
diff --git a/pcu/gen_links.sh b/pcu/gen_links.sh
index a33cb27..2e581d9 100755
--- a/pcu/gen_links.sh
+++ b/pcu/gen_links.sh
@@ -51,10 +51,10 @@
 DIR=../library
 FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc GSM_Types.ttcn GSM_RR_Types.ttcn Osmocom_Types.ttcn RLCMAC_Templates.ttcn RLCMAC_Types.ttcn RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn RLCMAC_EncDec.cc "
 FILES+="StatsD_Types.ttcn StatsD_CodecPort.ttcn StatsD_CodecPort_CtrlFunct.ttcn StatsD_CodecPort_CtrlFunctdef.cc StatsD_Checker.ttcn "
-FILES+="NS_Provider_IPL4.ttcn NS_Emulation.ttcnpp NS_CodecPort.ttcn NS_CodecPort_CtrlFunct.ttcn NS_CodecPort_CtrlFunctDef.cc "
+FILES+="NS_Provider_IPL4.ttcn NS_Emulation.ttcnpp "
 FILES+="BSSGP_Emulation.ttcnpp Osmocom_Gb_Types.ttcn "
 FILES+="LLC_Templates.ttcn L3_Templates.ttcn L3_Common.ttcn "
-FILES+="PCUIF_Types.ttcn PCUIF_CodecPort.ttcn RAW_NS.ttcn "
+FILES+="PCUIF_Types.ttcn PCUIF_CodecPort.ttcn RAW_NS.ttcnpp "
 gen_links $DIR $FILES
 
 ignore_pp_results
diff --git a/pcu/regen_makefile.sh b/pcu/regen_makefile.sh
index dc9b672..ca51452 100755
--- a/pcu/regen_makefile.sh
+++ b/pcu/regen_makefile.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-FILES="*.ttcn *.ttcnpp BSSGP_EncDec.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc NS_CodecPort_CtrlFunctDef.cc UD_PT.cc RLCMAC_EncDec.cc LLC_EncDec.cc TELNETasp_PT.cc Native_FunctionDefs.cc StatsD_CodecPort_CtrlFunctdef.cc"
+FILES="*.ttcn *.ttcnpp BSSGP_EncDec.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc UD_PT.cc RLCMAC_EncDec.cc LLC_EncDec.cc TELNETasp_PT.cc Native_FunctionDefs.cc StatsD_CodecPort_CtrlFunctdef.cc"
 
 export CPPFLAGS_TTCN3="-DBSSGP_EM_L3"