<p>laforge <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmocom-bb/+/14585">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  osmith: Looks good to me, approved
  Jenkins Builder: Verified

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">trx_toolkit/fake_trx.py: basic TRXD version 0x01 support<br><br>Since the new TRXD header format has been introduced, FakeTRX needs<br>to be able to fill it correctly. In particular, the following:<br><br>  - Modulation, which can be determined from the burst length;<br>  - Training Sequence Code (and set), which needs to be detected<br>    by comparing the burst bits of L12TRX message against known<br>    training sequences (only GMSK and the default TS set for now);<br>  - C/I (Carrier-to-Interference ratio), which can be simulated<br>    later on, as instructed on the TRXC interface ('FAKE_CI').<br><br>The actual TRXD header version is stored in the instance of class<br>DATAInterface. By default (at startup), legacy version 0 is used.<br>The version negotiation is supposed to be performed on the TRXC<br>interface, and to be implemented in a follow-up change.<br><br>Different Transceivers may use different header versions, thus in<br>FakeTRX.send_data_msg() we need to override the original version<br>of the L12TRX message, and generate the corresponding PDU.<br><br>Limitations:<br><br>  - NOPE / IDLE indications are not (yet) supported;<br>  - TSC detection: GMSK modulation only.<br><br>Change-Id: I164f5ae4ce7694d6e324aab927a04e96d489ebd8<br>Related: OS#4006<br>---<br>M src/target/trx_toolkit/burst_fwd.py<br>M src/target/trx_toolkit/data_if.py<br>M src/target/trx_toolkit/fake_trx.py<br>3 files changed, 78 insertions(+), 5 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/target/trx_toolkit/burst_fwd.py b/src/target/trx_toolkit/burst_fwd.py</span><br><span>index 164271f..1d5dd7b 100644</span><br><span>--- a/src/target/trx_toolkit/burst_fwd.py</span><br><span>+++ b/src/target/trx_toolkit/burst_fwd.py</span><br><span>@@ -84,4 +84,4 @@</span><br><span>                   if tx_msg.tn not in trx.ts_list:</span><br><span>                             continue</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-                    trx.send_data_msg(src_trx, tx_msg)</span><br><span style="color: hsl(120, 100%, 40%);">+                    trx.send_data_msg(src_trx, rx_msg, tx_msg)</span><br><span>diff --git a/src/target/trx_toolkit/data_if.py b/src/target/trx_toolkit/data_if.py</span><br><span>index 027fd85..10df438 100644</span><br><span>--- a/src/target/trx_toolkit/data_if.py</span><br><span>+++ b/src/target/trx_toolkit/data_if.py</span><br><span>@@ -4,7 +4,7 @@</span><br><span> # TRX Toolkit</span><br><span> # DATA interface implementation</span><br><span> #</span><br><span style="color: hsl(0, 100%, 40%);">-# (C) 2017-2018 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+# (C) 2017-2019 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span> #</span><br><span> # All Rights Reserved</span><br><span> #</span><br><span>@@ -29,9 +29,29 @@</span><br><span> </span><br><span> class DATAInterface(UDPLink):</span><br><span>  def __init__(self, *udp_link_args):</span><br><span style="color: hsl(120, 100%, 40%);">+           # Default header version (legacy)</span><br><span style="color: hsl(120, 100%, 40%);">+             self._hdr_ver = 0x00</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>               UDPLink.__init__(self, *udp_link_args)</span><br><span>               log.debug("Init TRXD interface (%s)" % self.desc_link())</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+        def set_hdr_ver(self, ver):</span><br><span style="color: hsl(120, 100%, 40%);">+           if not ver in DATAMSG.known_versions:</span><br><span style="color: hsl(120, 100%, 40%);">+                 return False</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                self._hdr_ver = ver</span><br><span style="color: hsl(120, 100%, 40%);">+           return True</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def match_hdr_ver(self, msg):</span><br><span style="color: hsl(120, 100%, 40%);">+         if msg.ver == self._hdr_ver:</span><br><span style="color: hsl(120, 100%, 40%);">+                  return True</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         log.error("(%s) Rx DATA message (%s) with unexpected header "</span><br><span style="color: hsl(120, 100%, 40%);">+                         "version %u (!= expected %u), ignoring..."</span><br><span style="color: hsl(120, 100%, 40%);">+                        % (self.desc_link(), msg.desc_hdr(),</span><br><span style="color: hsl(120, 100%, 40%);">+                     msg.ver, self._hdr_ver))</span><br><span style="color: hsl(120, 100%, 40%);">+           return False</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>       def recv_raw_data(self):</span><br><span>             data, _ = self.sock.recvfrom(512)</span><br><span>            return data</span><br><span>@@ -49,6 +69,11 @@</span><br><span>                             "from R:%s:%u" % (self.remote_addr, self.remote_port))</span><br><span>                     return None</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+               # Make sure the header version matches</span><br><span style="color: hsl(120, 100%, 40%);">+                # the configured one (self._hdr_ver)</span><br><span style="color: hsl(120, 100%, 40%);">+          if not self.match_hdr_ver(msg):</span><br><span style="color: hsl(120, 100%, 40%);">+                       return None</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>                return msg</span><br><span> </span><br><span>       def recv_trx2l1_msg(self):</span><br><span>@@ -64,6 +89,11 @@</span><br><span>                              "from R:%s:%u" % (self.remote_addr, self.remote_port))</span><br><span>                     return None</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+               # Make sure the header version matches</span><br><span style="color: hsl(120, 100%, 40%);">+                # the configured one (self._hdr_ver)</span><br><span style="color: hsl(120, 100%, 40%);">+          if not self.match_hdr_ver(msg):</span><br><span style="color: hsl(120, 100%, 40%);">+                       return None</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>                return msg</span><br><span> </span><br><span>       def send_msg(self, msg, legacy = False):</span><br><span>diff --git a/src/target/trx_toolkit/fake_trx.py b/src/target/trx_toolkit/fake_trx.py</span><br><span>index 928333f..de0e6ff 100755</span><br><span>--- a/src/target/trx_toolkit/fake_trx.py</span><br><span>+++ b/src/target/trx_toolkit/fake_trx.py</span><br><span>@@ -35,9 +35,11 @@</span><br><span> from app_common import ApplicationBase</span><br><span> from burst_fwd import BurstForwarder</span><br><span> from transceiver import Transceiver</span><br><span style="color: hsl(120, 100%, 40%);">+from data_msg import Modulation</span><br><span> from clck_gen import CLCKGen</span><br><span> from trx_list import TRXList</span><br><span> from fake_pm import FakePM</span><br><span style="color: hsl(120, 100%, 40%);">+from gsm_shared import *</span><br><span> </span><br><span> class FakeTRX(Transceiver):</span><br><span>      """ Fake transceiver with RF path (burst loss, RSSI, TA, ToA) simulation.</span><br><span>@@ -98,18 +100,21 @@</span><br><span> </span><br><span>  TOA256_BASE_DEFAULT = 0</span><br><span>      RSSI_BASE_DEFAULT = -60</span><br><span style="color: hsl(120, 100%, 40%);">+       CI_BASE_DEFAULT = 90</span><br><span> </span><br><span>     def __init__(self, *trx_args, **trx_kwargs):</span><br><span>                 Transceiver.__init__(self, *trx_args, **trx_kwargs)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-         # Actual ToA / RSSI / TA values</span><br><span style="color: hsl(120, 100%, 40%);">+               # Actual ToA, RSSI, C/I, TA values</span><br><span>           self.toa256_base = self.TOA256_BASE_DEFAULT</span><br><span>          self.rssi_base = self.RSSI_BASE_DEFAULT</span><br><span style="color: hsl(120, 100%, 40%);">+               self.ci_base = self.CI_BASE_DEFAULT</span><br><span>          self.ta = 0</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-         # ToA / RSSI randomization threshold</span><br><span style="color: hsl(120, 100%, 40%);">+          # ToA, RSSI, C/I randomization thresholds</span><br><span>            self.toa256_rand_threshold = 0</span><br><span>               self.rssi_rand_threshold = 0</span><br><span style="color: hsl(120, 100%, 40%);">+          self.ci_rand_threshold = 0</span><br><span> </span><br><span>               # Path loss simulation (burst dropping)</span><br><span>              self.burst_drop_amount = 0</span><br><span>@@ -137,6 +142,17 @@</span><br><span>            rssi_max = self.rssi_base + self.rssi_rand_threshold</span><br><span>                 return random.randint(rssi_min, rssi_max)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ @property</span><br><span style="color: hsl(120, 100%, 40%);">+     def ci(self):</span><br><span style="color: hsl(120, 100%, 40%);">+         # Check if randomization is required</span><br><span style="color: hsl(120, 100%, 40%);">+          if self.ci_rand_threshold is 0:</span><br><span style="color: hsl(120, 100%, 40%);">+                       return self.ci_base</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         # Generate a random C/I value in required range</span><br><span style="color: hsl(120, 100%, 40%);">+               ci_min = self.ci_base - self.ci_rand_threshold</span><br><span style="color: hsl(120, 100%, 40%);">+                ci_max = self.ci_base + self.ci_rand_threshold</span><br><span style="color: hsl(120, 100%, 40%);">+                return random.randint(ci_min, ci_max)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>      # Path loss simulation: burst dropping</span><br><span>       # Returns: True - drop, False - keep</span><br><span>         def sim_burst_drop(self, msg):</span><br><span>@@ -152,14 +168,41 @@</span><br><span> </span><br><span>           return False</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+      def _handle_data_msg_v1(self, src_msg, msg):</span><br><span style="color: hsl(120, 100%, 40%);">+          # TODO: NOPE indications are not (yet) supported</span><br><span style="color: hsl(120, 100%, 40%);">+              msg.nope_ind = False</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                # C/I (Carrier-to-Interference ratio)</span><br><span style="color: hsl(120, 100%, 40%);">+         msg.ci = self.ci</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            # Pick modulation type by burst length</span><br><span style="color: hsl(120, 100%, 40%);">+                bl = len(src_msg.burst)</span><br><span style="color: hsl(120, 100%, 40%);">+               msg.mod_type = Modulation.pick_by_bl(bl)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            # Pick TSC (Training Sequence Code) and TSC set</span><br><span style="color: hsl(120, 100%, 40%);">+               if msg.mod_type is Modulation.ModGMSK:</span><br><span style="color: hsl(120, 100%, 40%);">+                        ss = TrainingSeqGMSK.pick(src_msg.burst)</span><br><span style="color: hsl(120, 100%, 40%);">+                      msg.tsc = ss.tsc if ss is not None else 0</span><br><span style="color: hsl(120, 100%, 40%);">+                     msg.tsc_set = ss.tsc_set if ss is not None else 0</span><br><span style="color: hsl(120, 100%, 40%);">+             else: # TODO: other modulation types (at least 8-PSK)</span><br><span style="color: hsl(120, 100%, 40%);">+                 msg.tsc_set = 0</span><br><span style="color: hsl(120, 100%, 40%);">+                       msg.tsc = 0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>        # Takes (partially initialized) TRX2L1 message,</span><br><span>      # simulates RF path parameters (such as RSSI),</span><br><span>       # and sends towards the L1</span><br><span style="color: hsl(0, 100%, 40%);">-      def send_data_msg(self, src_trx, msg):</span><br><span style="color: hsl(120, 100%, 40%);">+        def send_data_msg(self, src_trx, src_msg, msg):</span><br><span style="color: hsl(120, 100%, 40%);">+               # Override header version</span><br><span style="color: hsl(120, 100%, 40%);">+             msg.ver = self.data_if._hdr_ver</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>            # Complete message header</span><br><span>            msg.toa256 = self.toa256</span><br><span>             msg.rssi = self.rssi</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+              # Version specific fields</span><br><span style="color: hsl(120, 100%, 40%);">+             if msg.ver >= 0x01:</span><br><span style="color: hsl(120, 100%, 40%);">+                        self._handle_data_msg_v1(src_msg, msg)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>             # Apply optional Timing Advance</span><br><span>              if src_trx.ta is not 0:</span><br><span>                      msg.toa256 -= src_trx.ta * 256</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmocom-bb/+/14585">change 14585</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/osmocom-bb/+/14585"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmocom-bb </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I164f5ae4ce7694d6e324aab927a04e96d489ebd8 </div>
<div style="display:none"> Gerrit-Change-Number: 14585 </div>
<div style="display:none"> Gerrit-PatchSet: 6 </div>
<div style="display:none"> Gerrit-Owner: fixeria <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: Hoernchen <ewild@sysmocom.de> </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@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: osmith <osmith@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>