BSSGP_Emulation: Support multiple PTP-BVC within one Entity

The existing BSSGP_Emulation is built around the assumption that every
instance of BSSGP_Emulation only servers one signaling-BVC and one
PTP-BVC.  While this is true for osmo-pcu at this point (BTS-colocated
PCU), other BSS/PCU implementations differ.

In general, there can always be any number of PTP BVC (one per cell)
next to the signaling BVC (one per BSS).  Let's represent this in
BSSGP_Emulation so we can create more comprehensive tests.

Change-Id: I7e30b4c4e188518a574e082962fba457b3a97ce3
diff --git a/pcu/PCU_Tests.default b/pcu/PCU_Tests.default
index a2dba4f..9944043 100644
--- a/pcu/PCU_Tests.default
+++ b/pcu/PCU_Tests.default
@@ -10,18 +10,23 @@
 [MODULE_PARAMETERS]
 SGSN_Components.mp_gb_cfg := {
 	nsei := 1234,
-	bvci := 1234,
-	cell_id := {
-		ra_id := {
-			lai := {
-				mcc_mnc := '262F42'H, lac := 13135
+	sgsn_role := true,
+	bvc := {
+		{
+			bvci := 1234,
+			cell_id := {
+				ra_id := {
+					lai := {
+						mcc_mnc := '262F42'H, lac := 13135
+					},
+					rac := 0
+				},
+				cell_id := 20960
 			},
-			rac := 0
-		},
-		cell_id := 20960
-	},
-	sgsn_role := true
-}
+			depth := BSSGP_DECODE_DEPTH_BSSGP
+		}
+	}
+};
 Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoPCU";
 PCUIF_Types.mp_pcuif_version := 10;
 StatsD_Checker.mp_enable_stats := true;
diff --git a/pcu/PCU_Tests.ttcn b/pcu/PCU_Tests.ttcn
index f68485a..b2f8b75 100644
--- a/pcu/PCU_Tests.ttcn
+++ b/pcu/PCU_Tests.ttcn
@@ -83,7 +83,7 @@
 	cell_id := 20960,
 	repeat_time := 5 * 50,
 	repeat_count := 3,
-	bvci := mp_gb_cfg.bvci,
+	bvci := mp_gb_cfg.bvc[0].bvci,
 	t3142 := 20,
 	t3169 := 5,
 	t3191 := 5,
@@ -215,12 +215,12 @@
 	activate(as_Tguard_RAW());
 
 	/* Init PCU interface component */
-	vc_PCUIF := RAW_PCUIF_CT.create("PCUIF-" & id);
+	vc_PCUIF := RAW_PCUIF_CT.create("PCUIF");
 	connect(vc_PCUIF:MTC, self:PCUIF);
 	map(vc_PCUIF:PCU, system:PCU);
 
 	/* Create one BTS component (we may want more some day) */
-	vc_BTS := RAW_PCU_BTS_CT.create("BTS-" & id);
+	vc_BTS := RAW_PCU_BTS_CT.create("BTS");
 	connect(vc_BTS:PCUIF, vc_PCUIF:BTS);
 	connect(vc_BTS:TC, self:BTS);
 
@@ -239,7 +239,7 @@
 }
 
 testcase TC_pcuif_suspend() runs on RAW_PCU_Test_CT {
-	var octetstring ra_id := enc_RoutingAreaIdentification(mp_gb_cfg.cell_id.ra_id);
+	var octetstring ra_id := enc_RoutingAreaIdentification(mp_gb_cfg.bvc[0].cell_id.ra_id);
 	var GprsTlli tlli := 'FFFFFFFF'O;
 	timer T;
 
@@ -256,7 +256,7 @@
 
 	T.start(2.0);
 	alt {
-	[] BSSGP_SIG[0].receive(tr_BSSGP_SUSPEND(tlli, mp_gb_cfg.cell_id.ra_id)) {
+	[] BSSGP_SIG[0].receive(tr_BSSGP_SUSPEND(tlli, mp_gb_cfg.bvc[0].cell_id.ra_id)) {
 		setverdict(pass);
 		}
 	[] T.timeout {
@@ -890,7 +890,7 @@
 	f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
 
 	/* receive one message on BSSGP with all aggregated data in payload: */
-	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, total_payload));
+	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, total_payload));
 }
 
 /* Verify PCU handles correctly CS1..4 with all possible LLC payload sizes fitting alone in one RLC block */
@@ -936,7 +936,7 @@
 	/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
 	f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
 	/* receive one message on BSSGP with all aggregated data in payload: */
-	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, payload));
+	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, payload));
 
 	/* Test sending LLC PDUS of incrementing size */
 	var integer max_size := 49;
@@ -962,7 +962,7 @@
 		f_ms_tx_ul_block(ms, ul_data);
 
 		/* receive one message on BSSGP with all aggregated data in payload: */
-		BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, payload));
+		BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, payload));
 
 		/* we will receive UL ACK/NACK from time to time, handle it. */
 		f_rx_rlcmac_dl_block(dl_block, dl_fn);
@@ -1007,7 +1007,7 @@
 
 	T.start(0.5);
 	alt {
-	[] BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, ?)) {
+	[] BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, ?)) {
 		setverdict(fail, "LLC PDU in Malformed RLC block was forwarded");
 		f_shutdown(__BFILE__, __LINE__);
 	}
@@ -1082,7 +1082,7 @@
 	f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
 
 	/* UL block should be received in SGSN */
-	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id));
+	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
 
 	/* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
 	BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data));
@@ -1172,7 +1172,7 @@
 	f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
 
 	/* UL block should be received in SGSN */
-	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id));
+	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
 
 	/* Now SGSN sends some DL data, PCU will page on PACCH */
 	BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data));
@@ -1287,7 +1287,7 @@
 	f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
 
 	/* UL block should be received in SGSN */
-	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id));
+	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
 
 	f_shutdown(__BFILE__, __LINE__, final := true);
 }
@@ -1383,7 +1383,7 @@
 	f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
 
 	/* receive one message on BSSGP with all aggregated data in payload: */
-	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, total_payload));
+	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, total_payload));
 }
 
 /* Verify that if PCU doesn't get an ACK for first DL block after IMM ASS, it
@@ -1581,7 +1581,7 @@
 	f_ms_tx_ul_block(ms, ul_data);
 
 	/* UL block dataA should be received in SGSN */
-	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, dataA));
+	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, dataA));
 
 	/* UL RlcDataBlock(dataB finished, dataC starts and finishes, dataD starts) [BSN=2, CV=1] */
 	ul_data := t_RLCMAC_UL_DATA_TLLI(tfi := ms.ul_tbf.tfi,
@@ -1598,8 +1598,8 @@
 	f_ms_tx_ul_block(ms, ul_data);
 
 	/* UL block dataB and dataC should be received in SGSN */
-	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, dataB));
-	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, dataC));
+	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, dataB));
+	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, dataC));
 
 	/* UL RlcDataBlock(dataD finishes) [BSN=3, CV=0] */
 	ul_data := t_RLCMAC_UL_DATA_TLLI(tfi := ms.ul_tbf.tfi,
@@ -1613,7 +1613,7 @@
 	f_ms_tx_ul_block(ms, ul_data);
 
 	/* UL block dataB and dataD should be received in SGSN */
-	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, dataD));
+	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, dataD));
 
 	f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
 	/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
@@ -1656,7 +1656,7 @@
 	f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true);
 
 	/* UL block should be received in SGSN */
-	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id));
+	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
 
 	acknack_tmpl := tr_RLCMAC_UL_ACK_NACK_GPRS(ms.ul_tbf.tfi,
 						   tr_UlAckNackGprs(ms.tlli,
@@ -1677,7 +1677,7 @@
 	f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := false);  /* TODO: send using cs_mcs */
 
 	/* UL block should be received in SGSN */
-	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id));
+	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
 
 	f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn, acknack_tmpl);
 	/* ACK the ACK */
@@ -1811,7 +1811,7 @@
 }
 
 testcase TC_paging_cs_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
-	f_tc_paging_cs_from_sgsn(mp_gb_cfg.bvci);
+	f_tc_paging_cs_from_sgsn(mp_gb_cfg.bvc[0].bvci);
 }
 
 /* Test PS paging over Gb (SGSN->PCU->BTS[CCCH]).
@@ -1858,7 +1858,7 @@
 }
 
 testcase TC_paging_ps_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
-	f_tc_paging_ps_from_sgsn(mp_gb_cfg.bvci);
+	f_tc_paging_ps_from_sgsn(mp_gb_cfg.bvc[0].bvci);
 }
 
 /* Verify osmo-pcu handles DL UNIT_DATA from SGSN with IMSI IE correctly. See OS#4729 */
@@ -1894,7 +1894,7 @@
 	f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
 
 	/* UL block should be received in SGSN */
-	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id));
+	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
 
 	/* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
 	BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, imsi := ts_BSSGP_IMSI(ms.imsi)));
@@ -1953,7 +1953,7 @@
 	f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
 
 	/* UL block should be received in SGSN */
-	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id));
+	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
 
 	/* Now SGSN sends some DL data with an invalid IMSI */
 	BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, imsi := ts_BSSGP_IMSI('1122'H)));
diff --git a/pcu/PCU_Tests_NS.ttcn b/pcu/PCU_Tests_NS.ttcn
index 6a62f29..5ab5f8d 100644
--- a/pcu/PCU_Tests_NS.ttcn
+++ b/pcu/PCU_Tests_NS.ttcn
@@ -55,7 +55,7 @@
 
 	/* Wait for PCU_VERSION and return INFO_IND */
 	PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_TXT_IND(0, PCU_VERSION, ?)));
-	/* FIXME: make sure to use parameters from mp_gb_cfg.cell_id in the PCU INFO IND */
+	/* FIXME: make sure to use parameters from mp_gb_cfg.bvc[0].cell_id in the PCU INFO IND */
 	var template PCUIF_Message info_ind_msg := ts_PCUIF_INFO_IND(0, info_ind);
 	PCU.send(t_SD_PCUIF(g_pcu_conn_id, info_ind_msg));
 }
@@ -194,16 +194,16 @@
 
 	/* Expect BVC-RESET for signaling (0) and ptp BVCI */
 	if (mp_tolerate_bvc_reset_cellid) {
-		as_rx_bvc_reset_tx_ack(0, mp_gb_cfg.cell_id, oneshot := true);
+		as_rx_bvc_reset_tx_ack(0, mp_gb_cfg.bvc[0].cell_id, oneshot := true);
 	} else {
 		as_rx_bvc_reset_tx_ack(0, omit, oneshot := true);
 	}
-	as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvci, mp_gb_cfg.cell_id, oneshot := true);
-	as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvci, oneshot := true);
+	as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id, oneshot := true);
+	as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true);
 
 	/* wait for one FLOW-CONTROL BVC and then ACK any further in the future */
-	as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci, oneshot := true);
-	activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci));
+	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);
 }
 
diff --git a/pcu/PCU_Tests_SNS.ttcn b/pcu/PCU_Tests_SNS.ttcn
index 524d35c..dc4cd82 100644
--- a/pcu/PCU_Tests_SNS.ttcn
+++ b/pcu/PCU_Tests_SNS.ttcn
@@ -187,13 +187,13 @@
 	f_outgoing_ns_alive();
 
 	/* Expect BVC-RESET for signaling (0) and ptp BVCI */
-	as_rx_bvc_reset_tx_ack(0, mp_gb_cfg.cell_id, oneshot := true);
-	as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvci, mp_gb_cfg.cell_id, oneshot := true);
-	as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvci, oneshot := true);
+	as_rx_bvc_reset_tx_ack(0, mp_gb_cfg.bvc[0].cell_id, oneshot := true);
+	as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id, oneshot := true);
+	as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true);
 
 	/* wait for one FLOW-CONTROL BVC and then ACK any further in the future */
-	as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci, oneshot := true);
-	activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci));
+	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);
 }
 
@@ -220,20 +220,20 @@
 	f_outgoing_ns_alive(1);
 
 	if (sgsn_originated_reset) {
-		f_tx_bvc_reset_rx_ack(0, mp_gb_cfg.cell_id);
-		f_tx_bvc_reset_rx_ack(mp_gb_cfg.bvci, mp_gb_cfg.cell_id);
+		f_tx_bvc_reset_rx_ack(0, mp_gb_cfg.bvc[0].cell_id);
+		f_tx_bvc_reset_rx_ack(mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id);
 	} else {
 		/* Expect BVC-RESET for signaling (0) and ptp BVCI */
-		as_rx_bvc_reset_tx_ack(0, mp_gb_cfg.cell_id, oneshot := true);
-		as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvci, mp_gb_cfg.cell_id, oneshot := true);
+		as_rx_bvc_reset_tx_ack(0, mp_gb_cfg.bvc[0].cell_id, oneshot := true);
+		as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id, oneshot := true);
 	}
 	/* Expect UNBLOCK for ptp BVCI on signaling NS-VC (idx==0) */
-	as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvci, oneshot := true);
+	as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true);
 
 	/* wait for one FLOW-CONTROL BVC and then ACK any further in the future. Flow
 	 * control happens on the p-t-p BVCI and hence on index 1 */
-	as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci, oneshot := true, idx := 1);
-	activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci, idx := 1));
+	as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true, idx := 1);
+	activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci, idx := 1));
 }
 
 /* Test full IP-SNS bring-up with two NS-VCs, one sig-only and one user-only */
@@ -270,20 +270,20 @@
 	f_outgoing_ns_alive_no_ack(idx := 0);
 
 	if (sgsn_originated_reset) {
-		f_tx_bvc_reset_rx_ack(0, mp_gb_cfg.cell_id, idx := 1);
-		f_tx_bvc_reset_rx_ack(mp_gb_cfg.bvci, mp_gb_cfg.cell_id, idx := 1);
+		f_tx_bvc_reset_rx_ack(0, mp_gb_cfg.bvc[0].cell_id, idx := 1);
+		f_tx_bvc_reset_rx_ack(mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id, idx := 1);
 	} else {
 		/* Expect BVC-RESET for signaling BVCI=0 and ptp BVCI */
-		as_rx_bvc_reset_tx_ack(0, mp_gb_cfg.cell_id, oneshot := true, idx := 1);
-		as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvci, mp_gb_cfg.cell_id, oneshot := true, idx := 1);
+		as_rx_bvc_reset_tx_ack(0, mp_gb_cfg.bvc[0].cell_id, oneshot := true, idx := 1);
+		as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id, oneshot := true, idx := 1);
 	}
 	/* Expect UNBLOCK for ptp BVCI on signaling NS-VC (idx==1) */
-	as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvci, oneshot := true, idx := 1);
+	as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true, idx := 1);
 
 	/* wait for one FLOW-CONTROL BVC and then ACK any further in the future. Flow
 	 * control happens on the p-t-p BVCI and hence on index 1 */
-	as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci, oneshot := true, idx := 2);
-	activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci, idx := 2));
+	as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true, idx := 2);
+	activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci, idx := 2));
 }
 
 /* Test full IP-SNS bring-up with two NS-VCs, one sig-only and one user-only - and where
@@ -322,8 +322,8 @@
 	f_outgoing_ns_alive_no_ack(idx := 0);
 
 	/* Transmit BVC-RESET and expect no ACK*/
-	f_tx_bvc_reset_rx_ack(0, mp_gb_cfg.cell_id, idx := 1, exp_ack := false);
-	f_tx_bvc_reset_rx_ack(mp_gb_cfg.bvci, mp_gb_cfg.cell_id, idx := 1, exp_ack := false);
+	f_tx_bvc_reset_rx_ack(0, mp_gb_cfg.bvc[0].cell_id, idx := 1, exp_ack := false);
+	f_tx_bvc_reset_rx_ack(mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id, idx := 1, exp_ack := false);
 }
 
 /* Test adding new IP endpoints at runtime */
diff --git a/pcu/SGSN_Components.ttcn b/pcu/SGSN_Components.ttcn
index 4a94c03..2f1fa75 100644
--- a/pcu/SGSN_Components.ttcn
+++ b/pcu/SGSN_Components.ttcn
@@ -20,18 +20,22 @@
 modulepar {
 	BssgpConfig mp_gb_cfg := {
 		nsei := 1234,
-		bvci := 1234,
-		cell_id := {
-			ra_id := {
-				lai := {
-					mcc_mnc := '262F42'H, lac := 13135
-				},
-				rac := 0
-			},
-			cell_id := 20960
-		},
 		sgsn_role := true,
-		depth := BSSGP_DECODE_DEPTH_BSSGP
+		bvc := {
+			{
+				bvci := 1234,
+				cell_id := {
+					ra_id := {
+						lai := {
+							mcc_mnc := '262F42'H, lac := 13135
+						},
+						rac := 0
+					},
+					cell_id := 20960
+				},
+				depth := BSSGP_DECODE_DEPTH_BSSGP
+			}
+		}
 	};
 
 	NSConfiguration mp_nsconfig := {
@@ -55,6 +59,7 @@
 type component bssgp_CT extends BSSGP_Client_CT {
 	var NS_CT ns_component;
 	var BSSGP_CT bssgp_component;
+	port BSSGP_CT_PROC_PT PROC;
 	var boolean g_initialized := false;
 }
 
@@ -75,16 +80,22 @@
 	/* create a new NS component */
 	ns_component := NS_CT.create;
 	bssgp_component := BSSGP_CT.create;
-	/* connect our BSSGP port to the BSSGP Emulation */
-	connect(self:BSSGP[0], bssgp_component:BSSGP_SP);
-	connect(self:BSSGP_SIG[0], bssgp_component:BSSGP_SP_SIG);
-	connect(self:BSSGP_PROC[0], bssgp_component:BSSGP_PROC);
 	/* connect lower-end of BSSGP with BSSGP_CODEC_PORT (maps to NS_PT*/
 	connect(bssgp_component:BSCP, ns_component:NS_SP);
+	connect(self:PROC, bssgp_component:PROC);
 	ns_component.start(NSStart(mp_nsconfig));
-	bssgp_component.start(BssgpStart(mp_gb_cfg));
+	bssgp_component.start(BssgpStart(mp_gb_cfg, testcasename()));
 
-	f_bssgp_client_register(mmctx.imsi, mmctx.tlli, mp_gb_cfg.cell_id);
+	for (var integer i := 0; i < lengthof(mp_gb_cfg.bvc); i := i+1) {
+		var BSSGP_BVC_CT vc_BVC;
+		/* obtain reference for BVC component (created by BssgpStart) */
+		vc_BVC := f_bssgp_get_bvci_ct(mp_gb_cfg.bvc[i].bvci, PROC);
+		/* connect our BSSGP port to the BSSGP Emulation */
+		connect(self:BSSGP[i], vc_BVC:BSSGP_SP);
+		connect(self:BSSGP_SIG[i], vc_BVC:BSSGP_SP_SIG);
+		connect(self:BSSGP_PROC[i], vc_BVC:BSSGP_PROC);
+		f_bssgp_client_register(mmctx.imsi, mmctx.tlli);
+	}
 }
 
 /* Establish BSSGP connection to PCU */
@@ -93,7 +104,7 @@
 
 	T.start
 	alt {
-	[] BSSGP[0].receive(t_BssgpStsInd(?, ?, BVC_S_UNBLOCKED)) { }
+	[] BSSGP[0].receive(tr_BssgpStsInd(*, ?, BVC_S_UNBLOCKED)) { }
 	[] BSSGP[0].receive { repeat; }
 	[] T.timeout {
 		setverdict(fail, "Timeout establishing BSSGP connection");