Change in osmo-ttcn3-hacks[master]: NS_Emulation: Introduce Load Sharing Function

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

laforge gerrit-no-reply at lists.osmocom.org
Thu Nov 12 20:02:09 UTC 2020


laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/21109 )

Change subject: NS_Emulation: Introduce Load Sharing Function
......................................................................

NS_Emulation: Introduce Load Sharing Function

The Load Sharing Function distributes traffic among all unblocked NS-VC
within a NS-VCG.  The sharing is done based on a LSP (Link Selector
Parameter) which is passed with the NS-UNITDATA.req primitive from BSSGP
to NS.  Details are implementation specific, but NS must ensure that all
traffic of one LSP is always sent through the same NS-VC, as long as
that NS-VC is alive/unblocked.

We use the LSP as follows:
* Signaling BVC always only uses lsp 0
* PTP BVC messages unrelated to user straffic use a per-BVC static LSP,
  which is the BVCI
* User traffic can set whatever LSP it wants
* NS keeps an array of NSVCs currently unblocked and uses the LSP modulo
  the array size as an index into it

Change-Id: I8b960ec4d729f50cadca353bb52685311cd45eed
Related: SYS#5084
---
M library/BSSGP_Emulation.ttcnpp
M library/NS_Emulation.ttcnpp
2 files changed, 68 insertions(+), 36 deletions(-)

Approvals:
  laforge: Looks good to me, approved
  pespin: Looks good to me, but someone else must approve
  Jenkins Builder: Verified



diff --git a/library/BSSGP_Emulation.ttcnpp b/library/BSSGP_Emulation.ttcnpp
index 1370958..cb0c82c 100644
--- a/library/BSSGP_Emulation.ttcnpp
+++ b/library/BSSGP_Emulation.ttcnpp
@@ -274,14 +274,14 @@
 	/* Respond to RESET for signalling BVCI 0 */
 	[] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, 0, omit), 0)) -> value udi {
 		log("Rx BVC-RESET for Signaling BVCI=0");
-		BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(0, omit), 0));
+		BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(0, omit), 0, 0));
 		f_sign_change_state(BVC_S_UNBLOCKED);
 	}
 
 	/* work-around for old, buggy libosmogb before Change-Id Ie87820537d6d616da4fd4bbf73eab06e28fda5e1 */
 	[mp_tolerate_bvc_reset_cellid] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, 0, g_cfg.bvc[0].cell_id), 0)) -> value udi {
 		log("Rx BVC-RESET for Signaling BVCI=0");
-		BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(0, omit), 0));
+		BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(0, omit), 0, 0));
 		f_sign_change_state(BVC_S_UNBLOCKED);
 	}
 }
@@ -301,7 +301,7 @@
 			BVC.send(udi) to bvc_comp_ref;
 		} else {
 			setverdict(fail, "Rx BSSGP for unknown PTP BVCI ", udi.bvci, ": ", udi.bssgp);
-			BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(udi.bvci, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), udi.bvci));
+			BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(udi.bvci, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), udi.bvci, 0));
 		}
 	}
 
@@ -324,7 +324,7 @@
 				BVC.send(udi) to bvc_comp_ref;
 			} else {
 				setverdict(fail, "Rx SIG BSSGP for unknown PTP BVCI ", ptp_bvci, ": ", udi.bssgp);
-				BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(udi.bvci, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), 0));
+				BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(udi.bvci, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), 0, 0));
                         }
 		}
 	}
@@ -362,7 +362,7 @@
 	[] BSCP.receive(NsStatusIndication:{g_cfg.nsei,?, complement (NSVC_S_ALIVE_UNBLOCKED), NSVC_S_ALIVE_UNBLOCKED, true}) -> value nsi {
 		/* if we just became NS-unblocked, send a BCC-RESET */
 		if (g_cfg.sgsn_role == false) {
-			BSCP.send(f_BnsUdReq(ts_BVC_RESET(BSSGP_CAUSE_OM_INTERVENTION, 0, omit), 0));
+			BSCP.send(f_BnsUdReq(ts_BVC_RESET(BSSGP_CAUSE_OM_INTERVENTION, 0, omit), 0, 0));
 			g_T2.start;
 			/* The BVC_RESET_ACK is handled in the as_sig_allstate() below */
 		}
@@ -383,7 +383,7 @@
 	/* Respond to RESET for signalling BVCI 0 */
 	[] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, 0, omit), 0)) -> value udi {
 		log("Rx BVC-RESET for Signaling BVCI=0");
-		BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(0, omit), 0));
+		BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(0, omit), 0, 0));
 		for (var integer i := 0; i < sizeof(BvcTable); i := i+1) {
 			if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
 				BVC.send(BssgpResetIndication:{0}) to BvcTable[i].comp_ref;
@@ -408,14 +408,14 @@
 	/* Respond to BLOCK for wrong BVCI */
 	[] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK(?, ?), 0)) -> value udi {
 		setverdict(fail, "Rx BVC-BLOCK for unknown BVCI");
-		BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(0, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), 0));
+		BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(0, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), 0, 0));
 	}
 
 	/* Respond to RESET with wrong BVCI */
 	[] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, ?, ?), 0)) -> value udi {
 		var BssgpBvci ptp_bvci := oct2int(udi.bssgp.pDU_BSSGP_BVC_RESET.bVCI.unstructured_value);
 		setverdict(fail, "Rx BVC-RESET for unknown BVCI ", ptp_bvci);
-		BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(ptp_bvci, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), 0));
+		BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(ptp_bvci, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), 0, 0));
 	}
 
 	/* BVC-RESET-ACK for BVCI=0 while T2 is running: Answer to a BVC-RESET we sent earlier */
@@ -431,14 +431,14 @@
 	}
 	[] g_T2.timeout {
 		setverdict(fail, "Timeout waiting for BVC-RESET-ACK on BVCI=0");
-		BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(udi.bvci, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), 0));
+		BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(udi.bvci, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), 0, 0));
 		g_T2.start;
 	}
 
 	/* default case of handling unknown PDUs */
 	[] BSCP.receive(f_BnsUdInd(?, ?)) -> value udi {
 		setverdict(fail, "Rx Unexpected BSSGP PDU ", udi.bssgp,"  in state ", g_sign_bvc_state);
-		BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(0, BSSGP_CAUSE_PDU_NOT_COMPATIBLE_WITH_PROTOCOL_STATE, udi.bssgp), 0));
+		BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(0, BSSGP_CAUSE_PDU_NOT_COMPATIBLE_WITH_PROTOCOL_STATE, udi.bssgp), 0, 0));
 	}
 
 	/* Forwarding of ASP_Event to per-BVC components */
@@ -531,11 +531,12 @@
 }
 
 /* generate a send template. Cannot be a real template as we want to use g_cfg.nsei */
-private function f_BnsUdReq(template PDU_BSSGP pdu, BssgpBvci bvci)
+private function f_BnsUdReq(template PDU_BSSGP pdu, BssgpBvci bvci, integer lsp)
 runs on BSSGP_CT return NsUnitdataRequest {
 	var NsUnitdataRequest udr := {
 		bvci := bvci,
 		nsei := g_cfg.nsei,
+		lsp := lsp,
 		/* for some weird reason we get "Dynamic test case error: Text encoder: Encoding an
 		 * unbound integer value." when trying to send the reocrd rather than the octetstring */
 		//sdu := omit,
@@ -610,6 +611,9 @@
 	var BssgpBvcConfig g_cfg;
 	var boolean g_sgsn_role;
 
+	/* default Link Selector Parameter for this BVC (for traffic unrelated to a TLLI) */
+	var integer g_bvc_lsp;
+
 	var BvcState g_ptp_bvc_state := BVC_S_BLOCKED;
 	timer g_T1 := 15.0;
 	timer g_T2 := 60.0;
@@ -871,20 +875,20 @@
 }
 
 private function f_ptp_sendUnblock() runs on BSSGP_BVC_CT {
-	BVC.send(ts_ptp_BnsUdReq(t_BVC_UNBLOCK(g_cfg.bvci), 0));
+	BVC.send(ts_ptp_BnsUdReq(t_BVC_UNBLOCK(g_cfg.bvci), 0, g_bvc_lsp));
 	g_t1_waits_for_block_ack := false;
 	g_T1.start;
 }
 
 private function f_ptp_sendBlock(BssgpCause cause) runs on BSSGP_BVC_CT {
-	BVC.send(ts_ptp_BnsUdReq(t_BVC_BLOCK(g_cfg.bvci, cause), 0));
+	BVC.send(ts_ptp_BnsUdReq(t_BVC_BLOCK(g_cfg.bvci, cause), 0, g_bvc_lsp));
 	g_t1_waits_for_block_ack := true;
 	g_T1.start;
 }
 
 private function f_ptp_sendStatus(BssgpCause cause, PDU_BSSGP pdu) runs on BSSGP_BVC_CT {
 	/* FIXME: Make sure correct Signaling or PTP BVCI is used! */
-	BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_STATUS(g_cfg.bvci, cause, pdu), g_cfg.bvci));
+	BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_STATUS(g_cfg.bvci, cause, pdu), g_cfg.bvci, g_bvc_lsp));
 }
 
 private function f_ptp_sendReset() runs on BSSGP_BVC_CT {
@@ -900,7 +904,7 @@
 	}
 
 	/* BVC-RESET is always sent via the SIGNALLING BVCI, see Table 5.4.1 */
-	BVC.send(ts_ptp_BnsUdReq(pdu, 0));
+	BVC.send(ts_ptp_BnsUdReq(pdu, 0, g_bvc_lsp));
 	g_T2.start;
 	//f_change_state(BVC_S_WAIT_RESET);
 }
@@ -946,11 +950,11 @@
 
 	/* bogus unblock, just respond with ACK */
 	[] BVC.receive(tr_ptp_BnsUdInd(t_BVC_UNBLOCK(g_cfg.bvci), 0)) -> value udi {
-		BVC.send(ts_ptp_BnsUdReq(t_BVC_UNBLOCK_ACK(g_cfg.bvci), 0));
+		BVC.send(ts_ptp_BnsUdReq(t_BVC_UNBLOCK_ACK(g_cfg.bvci), 0, g_bvc_lsp));
 	}
 	/* Respond to BLOCK with BLOCK-ACK + change state */
 	[] BVC.receive(tr_ptp_BnsUdInd(t_BVC_BLOCK(g_cfg.bvci, ?), 0)) -> value udi {
-		BVC.send(ts_ptp_BnsUdReq(t_BVC_BLOCK_ACK(g_cfg.bvci), 0));
+		BVC.send(ts_ptp_BnsUdReq(t_BVC_BLOCK_ACK(g_cfg.bvci), 0, g_bvc_lsp));
 		g_T1.stop;
 		f_ptp_change_state(BVC_S_BLOCKED);
 	}
@@ -970,7 +974,7 @@
 	/* simply acknowledge all per-BVC Flow Control Messages */
 	[g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_FC_BVC, g_cfg.bvci)) -> value udi {
 		var OCT1 tag := udi.bssgp.pDU_BSSGP_FLOW_CONTROL_BVC.tag.unstructured_Value;
-		BVC.send(ts_ptp_BnsUdReq(t_BVC_FC_BVC_ACK(tag), g_cfg.bvci));
+		BVC.send(ts_ptp_BnsUdReq(t_BVC_FC_BVC_ACK(tag), g_cfg.bvci, g_bvc_lsp));
 	}
 /*
 	[g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(t_BVC_FC_MS, g_cfg.bvci)) {
@@ -1017,44 +1021,48 @@
 
 	/* ConnHdlr sends BSSGP on BVCI=0 port: forward it to BSSGP_CT */
 	[] BSSGP_SP_SIG.receive(PDU_BSSGP:?)-> value bs_pdu sender vc_conn {
-		BVC.send(ts_ptp_BnsUdReq(bs_pdu, 0));
+		BVC.send(ts_ptp_BnsUdReq(bs_pdu, 0, g_bvc_lsp));
 	}
 
 	/* ConnHdlr sends BSSGP on BVCI=PTP port: forward it to BSSGP_CT */
 	[] BSSGP_SP.receive(PDU_BSSGP:?)-> value bs_pdu sender vc_conn {
-		BVC.send(ts_ptp_BnsUdReq(bs_pdu, g_cfg.bvci));
+		BVC.send(ts_ptp_BnsUdReq(bs_pdu, g_cfg.bvci, g_bvc_lsp));
 	}
 
 #ifdef BSSGP_EM_L3
 	/* ConnHdlr sends L3: Encode and send as UL_UD / DL_UD */
 	[g_sgsn_role] BSSGP_SP.receive(PDU_L3_SGSN_MS:?) -> value l3_mt sender vc_conn {
 		var integer idx := f_tbl_idx_by_comp(vc_conn);
+		var OCT4 tlli := ClientTable[idx].tlli;
 		var octetstring l3_enc := enc_PDU_L3_SGSN_MS(l3_mt);
 		var BIT4 sapi := f_llc_sapi_by_l3_mt(l3_mt);
 		var integer n_u := f_llc_get_n_u_tx(ClientTable[idx].llc[bit2int(sapi)]);
 		var octetstring llc_enc := enc_PDU_LLC(valueof(ts_LLC_UI(l3_enc, sapi, '1'B, n_u)));
-		BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_DL_UD(ClientTable[idx].tlli, llc_enc), g_cfg.bvci));
+		BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_DL_UD(tlli, llc_enc), g_cfg.bvci, oct2int(tlli)));
 	}
 	[not g_sgsn_role] BSSGP_SP.receive(PDU_L3_MS_SGSN:?) -> value l3_mo sender vc_conn {
 		var integer idx := f_tbl_idx_by_comp(vc_conn);
+		var OCT4 tlli := ClientTable[idx].tlli;
 		var octetstring l3_enc := enc_PDU_L3_MS_SGSN(l3_mo);
 		var BIT4 sapi := f_llc_sapi_by_l3_mo(l3_mo);
 		var integer n_u := f_llc_get_n_u_tx(ClientTable[idx].llc[bit2int(sapi)]);
 		var octetstring llc_enc := enc_PDU_LLC(valueof(ts_LLC_UI(l3_enc, sapi, '1'B, n_u)));
-		BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_UL_UD(ClientTable[idx].tlli, g_cfg.cell_id, llc_enc), g_cfg.bvci));
+		BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_UL_UD(tlli, g_cfg.cell_id, llc_enc), g_cfg.bvci, oct2int(tlli)));
 	}
 #endif
 
 	/* ConnHdlr sends raw LLC: Encode and send as UL_UD / DL_UD */
 	[not g_sgsn_role] BSSGP_SP.receive(PDU_LLC:?) -> value llc sender vc_conn {
 		var integer idx := f_tbl_idx_by_comp(vc_conn);
+		var OCT4 tlli := ClientTable[idx].tlli;
 		var octetstring llc_enc := enc_PDU_LLC(llc);
-		BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_UL_UD(ClientTable[idx].tlli, g_cfg.cell_id, llc_enc), g_cfg.bvci));
+		BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_UL_UD(tlli, g_cfg.cell_id, llc_enc), g_cfg.bvci, oct2int(tlli)));
 	}
 	[g_sgsn_role] BSSGP_SP.receive(PDU_LLC:?) -> value llc sender vc_conn {
 		var integer idx := f_tbl_idx_by_comp(vc_conn);
+		var OCT4 tlli := ClientTable[idx].tlli;
 		var octetstring llc_enc := enc_PDU_LLC(llc);
-		BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_DL_UD(ClientTable[idx].tlli, llc_enc), g_cfg.bvci));
+		BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_DL_UD(tlli, llc_enc), g_cfg.bvci, oct2int(tlli)));
 	}
 }
 
@@ -1081,7 +1089,7 @@
 	[g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_RESET(?, g_cfg.bvci, g_cfg.cell_id), 0)) -> value udi {
 		log("Rx BVC-RESET from BVCI=", g_cfg.bvci);
 		/* Respond to RESET with correct BVCI but without CellID */
-		BVC.send(ts_ptp_BnsUdReq(ts_BVC_RESET_ACK(g_cfg.bvci, omit), 0));
+		BVC.send(ts_ptp_BnsUdReq(ts_BVC_RESET_ACK(g_cfg.bvci, omit), 0, g_bvc_lsp));
 		/* FIXME: reset all state? What about clients? */
 		f_ptp_change_state(BVC_S_UNBLOCKED);
 	}
@@ -1089,7 +1097,7 @@
 	[not g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_RESET(?, g_cfg.bvci, omit), 0)) -> value udi {
 		log("Rx BVC-RESET from BVCI=", g_cfg.bvci);
 		/* Respond to RESET with correct BVCI with CellID */
-		BVC.send(ts_ptp_BnsUdReq(ts_BVC_RESET_ACK(g_cfg.bvci, g_cfg.cell_id), 0));
+		BVC.send(ts_ptp_BnsUdReq(ts_BVC_RESET_ACK(g_cfg.bvci, g_cfg.cell_id), 0, g_bvc_lsp));
 		/* FIXME: reset all state? What about clients? */
 		f_ptp_change_state(BVC_S_UNBLOCKED);
 	}
@@ -1138,13 +1146,16 @@
 /* main function for per-BVC Component */
 private function f_bssgp_bvc_main(BssgpBvcConfig cfg, boolean sgsn_role, charstring id) runs on BSSGP_BVC_CT {
 	g_cfg := cfg;
+	g_bvc_lsp := cfg.bvci;
 	g_sgsn_role := sgsn_role;
 	f_bssgp_bvc_ScanEvents();
 }
 
-template (value) NsUnitdataRequest ts_ptp_BnsUdReq(template (value) PDU_BSSGP pdu, template (value) BssgpBvci bvci) := {
+template (value) NsUnitdataRequest ts_ptp_BnsUdReq(template (value) PDU_BSSGP pdu, template (value) BssgpBvci bvci,
+						   template (value) integer lsp) := {
 	bvci := bvci,
 	nsei := 0, // overwritten in BSSGP_CT
+	lsp := lsp,
 	/* for some weird reason we get "Dynamic test case error: Text encoder: Encoding an
 	 * unbound integer value." when trying to send the reocrd rather than the octetstring */
 	//sdu := omit,
diff --git a/library/NS_Emulation.ttcnpp b/library/NS_Emulation.ttcnpp
index 7958938..19de9d3 100644
--- a/library/NS_Emulation.ttcnpp
+++ b/library/NS_Emulation.ttcnpp
@@ -24,24 +24,28 @@
 	type record NsUnitdataRequest {
 		BssgpBvci	bvci,
 		Nsei		nsei,
+		integer		lsp,
 		octetstring	sdu optional,
 		PDU_BSSGP	bssgp optional
 	}
 
-	template NsUnitdataRequest tr_NsUdReq(template Nsei nsei, template BssgpBvci bvci, template octetstring sdu,
-					      template PDU_BSSGP bssgp) := {
+	template NsUnitdataRequest tr_NsUdReq(template Nsei nsei, template BssgpBvci bvci, template integer lsp,
+					      template octetstring sdu, template PDU_BSSGP bssgp) := {
 		bvci := bvci,
 		nsei := nsei,
+		lsp := lsp,
 		sdu := sdu,
 		bssgp := bssgp
 	}
 
 	template (value) NsUnitdataRequest ts_NsUdReq(template (value) Nsei nsei,
 						      template (value) BssgpBvci bvci,
+						      template (value) integer lsp,
 						      template (omit) octetstring sdu,
 						      template (omit) PDU_BSSGP bssgp) := {
 		bvci := bvci,
 		nsei := nsei,
+		lsp := lsp,
 		sdu := sdu,
 		bssgp := bssgp
 	}
@@ -184,7 +188,8 @@
 
 		/* references to the per-NSVC components */
 		var NsvcTable g_nsvcs := {};
-
+		/* list of indexes to g_nsvcs[] of currently unblocked NSVCs */
+		var ro_integer g_unblocked_nsvcs := {};
 	};
 	type record NsvcTableEntry {
 		Nsvci nsvci,
@@ -192,6 +197,7 @@
 		NsvcState state
 	};
 	type record of NsvcTableEntry NsvcTable;
+	type record of integer ro_integer;
 
 	/* add one NSVC (component and table entry */
 	function f_nsvc_add(NSVCConfiguration nsvc_cfg) runs on NS_CT {
@@ -206,6 +212,7 @@
 		te.vc_conn.start(NSVCStart(nsvc_cfg, g_config, nsvc_id));
 
 		g_nsvcs := g_nsvcs & { te };
+		/* no need to add to g_unblocked_nsvcs, as state is always DEAD_BLOCKED above */
 	}
 
 	function f_nsvc_find_idx(Nsvci nsvci) runs on NS_CT return integer {
@@ -232,6 +239,19 @@
 		if (i < 0) {
 			return;
 		}
+		if (g_nsvcs[i].state != NSVC_S_ALIVE_UNBLOCKED and state == NSVC_S_ALIVE_UNBLOCKED) {
+			/* add index to list of unblocked NSVCs */
+			g_unblocked_nsvcs := g_unblocked_nsvcs & {i};
+		} else if (g_nsvcs[i].state == NSVC_S_ALIVE_UNBLOCKED and state != NSVC_S_ALIVE_UNBLOCKED) {
+			/* remove index to list of unblocked NSVCs */
+			var ro_integer new_unblocked_nsvcs := {};
+			for (var integer j := 0; j < lengthof(g_unblocked_nsvcs); j := j+1) {
+				if (g_unblocked_nsvcs[j] != i) {
+					new_unblocked_nsvcs := new_unblocked_nsvcs & {j};
+				}
+			}
+			g_unblocked_nsvcs := new_unblocked_nsvcs;
+		}
 		g_nsvcs[i].state := state;
 	}
 
@@ -302,11 +322,12 @@
 					log2str("Received UnitDataInd for invalid NSEI: ", rx_nsudi));
 			}
 		/* from user down to NS-VC */
-		[] NS_SP.receive(tr_NsUdReq(g_config.nsei, ?, ?, *)) -> value rx_nsudr {
-			/* FIXME: load distribution function */
-			NSVC.send(rx_nsudr) to g_nsvcs[0].vc_conn;
+		[] NS_SP.receive(tr_NsUdReq(g_config.nsei, ?, ?, ?, *)) -> value rx_nsudr {
+			/* load distribution function */
+			var integer nsvc_idx := g_unblocked_nsvcs[rx_nsudr.lsp mod lengthof(g_unblocked_nsvcs)];
+			NSVC.send(rx_nsudr) to g_nsvcs[nsvc_idx].vc_conn;
 			}
-		[] NS_SP.receive(tr_NsUdReq(?, ?, ?, *)) -> value rx_nsudr {
+		[] NS_SP.receive(tr_NsUdReq(?, ?, ?, ?, *)) -> value rx_nsudr {
 			Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
 					log2str("Received NsUnitdataReq for invalid NSEI: ", rx_nsudr));
 			}
@@ -564,11 +585,11 @@
 					     rf.pDU_NS_Unitdata.nS_SDU));
 		}
 		/* NS-UNITDATA.req from user to NS-UNITDATA PDU on network */
-		[] NS_SP.receive(tr_NsUdReq(g_config.nsei, ?, ?, omit)) -> value ud_req {
+		[] NS_SP.receive(tr_NsUdReq(g_config.nsei, ?, ?, ?, omit)) -> value ud_req {
 			/* using raw octetstring PDU */
 			NSCP.send(ts_NS_UNITDATA(t_SduCtrlB, ud_req.bvci, ud_req.sdu));
 		}
-		[] NS_SP.receive(tr_NsUdReq(g_config.nsei, ?, omit, ?)) -> value ud_req {
+		[] NS_SP.receive(tr_NsUdReq(g_config.nsei, ?, ?, omit, ?)) -> value ud_req {
 			/* using decoded BSSGP PDU that we need to encode first */
 			var octetstring enc := enc_PDU_BSSGP(ud_req.bssgp);
 			NSCP.send(ts_NS_UNITDATA(t_SduCtrlB, ud_req.bvci, enc));

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/21109
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: I8b960ec4d729f50cadca353bb52685311cd45eed
Gerrit-Change-Number: 21109
Gerrit-PatchSet: 3
Gerrit-Owner: laforge <laforge at osmocom.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: lynxis lazus <lynxis at fe80.eu>
Gerrit-Reviewer: pespin <pespin at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20201112/bc7efd52/attachment.htm>


More information about the gerrit-log mailing list