<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/21109">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  laforge: Looks good to me, approved
  pespin: Looks good to me, but someone else must approve
  Jenkins Builder: Verified

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

<div style="display:none"> Gerrit-Project: osmo-ttcn3-hacks </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I8b960ec4d729f50cadca353bb52685311cd45eed </div>
<div style="display:none"> Gerrit-Change-Number: 21109 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: lynxis lazus <lynxis@fe80.eu> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>