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

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">library/RSL_Emulation: server mode: handle multiple transceivers<br><br>Since change [1], the IPA emulation component allows us to handle<br>multiple IPA connections, thus multiple RSL connections. The idea<br>is to attach a TCP/IP connection identifier to each message.<br><br>On top of that, this change implements mapping between TCP/IP<br>connection identifiers and RSL stream identifiers, so we can<br>finally talk to any of connected transceivers (up to 4 for now),<br>not only the last connected one (as it was before). The actual<br>mapping is done during the IPA identification procedure.<br><br>Instead of forwarding ASP_IPA_EVENT_UP to a test case, the RSL<br>emulation component now sends a new event - RSLEM_EV_TRX_UP,<br>with transceiver number (actually, IPA stream-id) attached.<br><br>[1] I93c58c08cf296e5cea81d811650caa1a09b8a579<br><br>Change-Id: I86afb55ecc6703ce7a229aaa626223f9331a4778<br>Related: OS#4546<br>---<br>M bts/BTS_Tests.ttcn<br>M library/IPA_Types.ttcn<br>M library/RSL_Emulation.ttcn<br>3 files changed, 126 insertions(+), 6 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/bts/BTS_Tests.ttcn b/bts/BTS_Tests.ttcn</span><br><span>index 99a8ef9..7d211de 100644</span><br><span>--- a/bts/BTS_Tests.ttcn</span><br><span>+++ b/bts/BTS_Tests.ttcn</span><br><span>@@ -192,7 +192,8 @@</span><br><span> </span><br><span>     T.start;</span><br><span>     alt {</span><br><span style="color: hsl(0, 100%, 40%);">-   [] RSL_CCHAN.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP));</span><br><span style="color: hsl(120, 100%, 40%);">+        /* TODO: handle connection events from multiple transceivers */</span><br><span style="color: hsl(120, 100%, 40%);">+       [] RSL_CCHAN.receive(tr_RSLEm_EV(RSLEM_EV_TRX_UP));</span><br><span>  [] T.timeout {</span><br><span>               Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for ASP_IPA_EVENT_UP");</span><br><span>                }</span><br><span>diff --git a/library/IPA_Types.ttcn b/library/IPA_Types.ttcn</span><br><span>index ce6f9b6..110e5b1 100644</span><br><span>--- a/library/IPA_Types.ttcn</span><br><span>+++ b/library/IPA_Types.ttcn</span><br><span>@@ -131,5 +131,18 @@</span><br><span>        extension "decode(RAW)"</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* Finds an IE with the given tag in IPA IDENTITY RESPONSE.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns index of an IE if found, -1 otherwise. */</span><br><span style="color: hsl(120, 100%, 40%);">+function f_ipa_id_resp_find_ie(in IpaCcmIdResp resp, IpaCcmIdTag tag)</span><br><span style="color: hsl(120, 100%, 40%);">+return integer {</span><br><span style="color: hsl(120, 100%, 40%);">+   for (var integer i := 0; i < sizeof(resp); i := i + 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+           if (resp[i].tag == tag) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     return i;</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span> } with { encode "RAW" }</span><br><span>diff --git a/library/RSL_Emulation.ttcn b/library/RSL_Emulation.ttcn</span><br><span>index bbe5332..eeb5ed5 100644</span><br><span>--- a/library/RSL_Emulation.ttcn</span><br><span>+++ b/library/RSL_Emulation.ttcn</span><br><span>@@ -64,12 +64,33 @@</span><br><span>  fn := omit</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+type enumerated RSLEm_EventType {</span><br><span style="color: hsl(120, 100%, 40%);">+        RSLEM_EV_TRX_UP,</span><br><span style="color: hsl(120, 100%, 40%);">+      RSLEM_EV_TRX_DOWN</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%);">+type record RSLEm_Event {</span><br><span style="color: hsl(120, 100%, 40%);">+    RSLEm_EventType         ev_type,</span><br><span style="color: hsl(120, 100%, 40%);">+      IpaStreamId             sid</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%);">+template (value) RSLEm_Event ts_RSLEm_EV(RSLEm_EventType ev_type,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   IpaStreamId sid) := {</span><br><span style="color: hsl(120, 100%, 40%);">+        ev_type := ev_type,</span><br><span style="color: hsl(120, 100%, 40%);">+   sid := sid</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+template RSLEm_Event tr_RSLEm_EV(template RSLEm_EventType ev_type,</span><br><span style="color: hsl(120, 100%, 40%);">+                             template IpaStreamId sid := ?) := {</span><br><span style="color: hsl(120, 100%, 40%);">+  ev_type := ev_type,</span><br><span style="color: hsl(120, 100%, 40%);">+   sid := sid</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> type port RSL_DCHAN_PT message {</span><br><span>         inout RSLDC_ChanRqd, RSL_Message;</span><br><span> } with { extension "internal" };</span><br><span> </span><br><span> type port RSL_CCHAN_PT message {</span><br><span style="color: hsl(0, 100%, 40%);">- inout ASP_RSL_Unitdata, ASP_IPA_Event;</span><br><span style="color: hsl(120, 100%, 40%);">+        inout ASP_RSL_Unitdata, RSLEm_Event;</span><br><span> } with { extension "internal" };</span><br><span> </span><br><span> </span><br><span>@@ -314,6 +335,67 @@</span><br><span>    }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+private function f_trx_conn_map_init()</span><br><span style="color: hsl(120, 100%, 40%);">+runs on RSL_Emulation_CT {</span><br><span style="color: hsl(120, 100%, 40%);">+        for (var integer i := 0; i < sizeof(TrxConnMap); i := i + 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+             TrxConnMap[i] := -1;</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+private function f_trx_conn_map_register(integer conn_id, in IpaCcmIdResp id_resp)</span><br><span style="color: hsl(120, 100%, 40%);">+runs on RSL_Emulation_CT return IpaStreamId {</span><br><span style="color: hsl(120, 100%, 40%);">+     var template charstring unit_id_fmt := pattern "(\d+)/(\d+)/(\d+)";</span><br><span style="color: hsl(120, 100%, 40%);">+ var charstring unit_id;</span><br><span style="color: hsl(120, 100%, 40%);">+       var integer trx_nr;</span><br><span style="color: hsl(120, 100%, 40%);">+   var integer idx;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Check if we have room for a new connection */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (TrxConnNum >= sizeof(TrxConnMap)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            testcase.stop("We cannot handle more than ", sizeof(TrxConnMap), " transceivers");</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%);">+   /* Find IPAC_IDTAG_UNITID in the IPA IDENTITY RESPONSE */</span><br><span style="color: hsl(120, 100%, 40%);">+     idx := f_ipa_id_resp_find_ie(id_resp, IPAC_IDTAG_UNITID);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (idx < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+             testcase.stop("IPA IDENTITY RESPONSE contains no unit-id");</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%);">+   /* Make sure that IPA unit-id is valid */</span><br><span style="color: hsl(120, 100%, 40%);">+     unit_id := oct2char(id_resp[idx].data);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (not match(unit_id, unit_id_fmt)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                testcase.stop("IPA unit-id has unknown/unexpected format");</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%);">+   /* Parse transceiver number (site/bts/trx).</span><br><span style="color: hsl(120, 100%, 40%);">+    * TODO: implement and use declaratice types. */</span><br><span style="color: hsl(120, 100%, 40%);">+      unit_id := regexp(unit_id, unit_id_fmt, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+   trx_nr  := str2int(unit_id);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (trx_nr >= sizeof(TrxConnMap)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                testcase.stop("Transceiver #", trx_nr, " does not fit");</span><br><span style="color: hsl(120, 100%, 40%);">+  } else if (TrxConnMap[trx_nr] != -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+                testcase.stop("Transceiver #", trx_nr, " is already connected?!?");</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%);">+   /* Finally, store the connection ID */</span><br><span style="color: hsl(120, 100%, 40%);">+        log("Mapped TRX#", trx_nr, " to TCP/IP conn_id=", conn_id);</span><br><span style="color: hsl(120, 100%, 40%);">+       TrxConnMap[trx_nr] := conn_id;</span><br><span style="color: hsl(120, 100%, 40%);">+        TrxConnNum := TrxConnNum + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return f_streamId_by_trx(trx_nr);</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%);">+private function f_trx_conn_map_resolve(IpaStreamId id)</span><br><span style="color: hsl(120, 100%, 40%);">+runs on RSL_Emulation_CT return integer {</span><br><span style="color: hsl(120, 100%, 40%);">+    var integer trx_nr := f_trx_by_streamId(id);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (TrxConnMap[trx_nr] == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+               testcase.stop("Transceiver #", trx_nr, " is not connected");</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%);">+   return TrxConnMap[trx_nr];</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> type component RSL_Emulation_CT {</span><br><span>         /* port facing down towards IPA emulation */</span><br><span>         port IPA_RSL_PT IPA_PT;</span><br><span>@@ -329,6 +411,10 @@</span><br><span> </span><br><span>   /* last RSL CHAN ACT for each chan_nr */</span><br><span>     var LastActData LastActTable[64];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* IPA stream ID -> TCP/IP connection ID mapping for transceivers */</span><br><span style="color: hsl(120, 100%, 40%);">+       var integer TrxConnNum := 0; /* number of connected transceivers */</span><br><span style="color: hsl(120, 100%, 40%);">+   var integer TrxConnMap[4]; /* up to 4 transceivers for now */</span><br><span> }</span><br><span> </span><br><span> </span><br><span>@@ -356,12 +442,14 @@</span><br><span>   var RSL_DchanHdlr vc_conn;</span><br><span>   var RslChannelNr chan_nr;</span><br><span>    var uint8_t trx_nr;</span><br><span style="color: hsl(120, 100%, 40%);">+   var integer conn_id;</span><br><span>         var integer cid;</span><br><span>     var integer i;</span><br><span>       /* special synchronization handling during hand-over */</span><br><span>      var boolean dchan_suspended := false;</span><br><span> </span><br><span>    f_conn_table_init();</span><br><span style="color: hsl(120, 100%, 40%);">+  f_trx_conn_map_init();</span><br><span>       f_last_act_table_init();</span><br><span> </span><br><span>         while (true) {</span><br><span>@@ -369,7 +457,15 @@</span><br><span>                [bts_role] IPA_PT.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP)) {</span><br><span>                         }</span><br><span>            [not bts_role] IPA_PT.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP)) -> value evt {</span><br><span style="color: hsl(0, 100%, 40%);">-                        CCHAN_PT.send(evt);</span><br><span style="color: hsl(120, 100%, 40%);">+                   log("A new IPA/RSL connection has been established (conn_id=",</span><br><span style="color: hsl(120, 100%, 40%);">+                          evt.conn_id, "), waiting for IDENTITY RESPONSE...");</span><br><span style="color: hsl(120, 100%, 40%);">+                    }</span><br><span style="color: hsl(120, 100%, 40%);">+             [not bts_role] IPA_PT.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_RESP)) -> value evt {</span><br><span style="color: hsl(120, 100%, 40%);">+                 log("Got IDENTITY RESPONSE (conn_id=", evt.conn_id, "): ", evt.id_resp);</span><br><span style="color: hsl(120, 100%, 40%);">+                  /* Update [ IPA stream ID -> TCP/IP connection ID ] mapping */</span><br><span style="color: hsl(120, 100%, 40%);">+                     var IpaStreamId sid := f_trx_conn_map_register(evt.conn_id, evt.id_resp);</span><br><span style="color: hsl(120, 100%, 40%);">+                     /* Notify the upper layers about a new connection */</span><br><span style="color: hsl(120, 100%, 40%);">+                  CCHAN_PT.send(ts_RSLEm_EV(RSLEM_EV_TRX_UP, sid));</span><br><span>                    }</span><br><span>            [bts_role] IPA_PT.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {</span><br><span>                       Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Lost IPA connection!");</span><br><span>@@ -485,15 +581,25 @@</span><br><span>                        f_cid_create(chan_rqd.ra, chan_rqd.fn, vc_conn);</span><br><span>                     }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           [] CLIENT_PT.receive(tr_RSL_MsgType(?)) -> value rx_rsl_msg sender vc_conn {</span><br><span style="color: hsl(0, 100%, 40%);">-                 /* forward to BSC */</span><br><span style="color: hsl(120, 100%, 40%);">+          /* RSL message from a component that runs on RSL_DchanHdlr */</span><br><span style="color: hsl(120, 100%, 40%);">+         [bts_role] CLIENT_PT.receive(tr_RSL_MsgType(?)) -> value rx_rsl_msg sender vc_conn {</span><br><span>                      cid := f_cid_by_comp_ref(vc_conn);</span><br><span>                   IPA_PT.send(ts_ASP_RSL_UD(rx_rsl_msg, ConnectionTable[cid].stream_id));</span><br><span>                      }</span><br><span style="color: hsl(120, 100%, 40%);">+             [not bts_role] CLIENT_PT.receive(tr_RSL_MsgType(?)) -> value rx_rsl_msg sender vc_conn {</span><br><span style="color: hsl(120, 100%, 40%);">+                   cid := f_cid_by_comp_ref(vc_conn);</span><br><span style="color: hsl(120, 100%, 40%);">+                    conn_id := f_trx_conn_map_resolve(ConnectionTable[cid].stream_id);</span><br><span style="color: hsl(120, 100%, 40%);">+                    IPA_PT.send(ts_ASP_RSL_UD(rx_rsl_msg, ConnectionTable[cid].stream_id, conn_id));</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           [] CCHAN_PT.receive(tr_ASP_RSL_UD(?, sid := ?)) -> value rx_rsl {</span><br><span style="color: hsl(120, 100%, 40%);">+          /* RSL message from MTC */</span><br><span style="color: hsl(120, 100%, 40%);">+            [bts_role] CCHAN_PT.receive(tr_ASP_RSL_UD(?, sid := ?)) -> value rx_rsl {</span><br><span>                         IPA_PT.send(ts_ASP_RSL_UD(rx_rsl.rsl, rx_rsl.streamId));</span><br><span>                     }</span><br><span style="color: hsl(120, 100%, 40%);">+             [not bts_role] CCHAN_PT.receive(tr_ASP_RSL_UD(?, sid := ?)) -> value rx_rsl {</span><br><span style="color: hsl(120, 100%, 40%);">+                      conn_id := f_trx_conn_map_resolve(rx_rsl.streamId);</span><br><span style="color: hsl(120, 100%, 40%);">+                   IPA_PT.send(ts_ASP_RSL_UD(rx_rsl.rsl, rx_rsl.streamId, conn_id));</span><br><span style="color: hsl(120, 100%, 40%);">+                     }</span><br><span> </span><br><span>                /* explicit registration, e.g. in (non-immediate) assignment case */</span><br><span>                 [] RSL_PROC.getcall(RSLEM_register:{?,?,?}) -> param(trx_nr, chan_nr, vc_conn) {</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/18465">change 18465</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/+/18465"/><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: I86afb55ecc6703ce7a229aaa626223f9331a4778 </div>
<div style="display:none"> Gerrit-Change-Number: 18465 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: fixeria <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: fixeria <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>