<p>Vadim Yanitskiy <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/12325">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Jenkins Builder: Verified
Harald Welte: Looks good to me, approved
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">trx_toolkit/fake_trx.py: handle multiple transceivers<br><br>Since Ice44e2b22566b3652ef6d43896055963b13ab185 is merged, the class<br>hierarchy has become much more flexible, so it's possible to create<br>multiple Transceiver / FakeTRX instances and distribute bursts using<br>a single instance of BurstForwarder.<br><br>This change introduces a new command line option, that can be used<br>to specify additional transceivers. Please note that fake_trx.py<br>still initializes a pair of BTS and BB transceivers by default.<br><br>The new option has the following format:<br><br> --trx REMOTE_ADDR:BASE_PORT[/TRX_NUM]<br><br>Some examples for IPv4 and IPv6:<br><br> --trx 127.0.0.1:5703<br> --trx [2001:0db8:85a3:0000:0000:8a2e:0370:7334]:6703<br><br>If optional TRX_NUM > 0 is specified, e.g.:<br><br> --trx 127.0.0.1:5700/1<br><br>then this transceiver is considered as a child of another one.<br>See I7e97b7f32dde7ab74779133e9d7504f1d0fce60c for details.<br><br>Change-Id: Ibff31fb3a958a714c828d0dea7e87d47f778fd80<br>---<br>M src/target/trx_toolkit/fake_trx.py<br>1 file changed, 81 insertions(+), 31 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/target/trx_toolkit/fake_trx.py b/src/target/trx_toolkit/fake_trx.py</span><br><span>index 46b413a..0f473d0 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>@@ -30,11 +30,13 @@</span><br><span> import random</span><br><span> import select</span><br><span> import sys</span><br><span style="color: hsl(120, 100%, 40%);">+import re</span><br><span> </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> from clck_gen import CLCKGen</span><br><span style="color: hsl(120, 100%, 40%);">+from trx_list import TRXList</span><br><span> from fake_pm import FakePM</span><br><span> </span><br><span> class FakeTRX(Transceiver):</span><br><span>@@ -270,6 +272,34 @@</span><br><span> # Configure logging</span><br><span> self.app_init_logging(self.argv)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ # List of all transceivers</span><br><span style="color: hsl(120, 100%, 40%);">+ self.trx_list = TRXList()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def append_trx(self, remote_addr, base_port):</span><br><span style="color: hsl(120, 100%, 40%);">+ trx = FakeTRX(self.argv.trx_bind_addr, remote_addr, base_port,</span><br><span style="color: hsl(120, 100%, 40%);">+ clck_gen = self.clck_gen, pwr_meas = self.fake_pm)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.trx_list.add_trx(trx)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def append_child_trx(self, remote_addr, base_port, child_idx):</span><br><span style="color: hsl(120, 100%, 40%);">+ # Index 0 corresponds to the first transceiver</span><br><span style="color: hsl(120, 100%, 40%);">+ if child_idx is 0:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.append_trx(remote_addr, base_port)</span><br><span style="color: hsl(120, 100%, 40%);">+ return</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # Find 'parent' transceiver for a new child</span><br><span style="color: hsl(120, 100%, 40%);">+ trx_parent = self.trx_list.find_trx(remote_addr, base_port)</span><br><span style="color: hsl(120, 100%, 40%);">+ if trx_parent is None:</span><br><span style="color: hsl(120, 100%, 40%);">+ raise IndexError("Couldn't find parent transceiver "</span><br><span style="color: hsl(120, 100%, 40%);">+ "for '%s:%d/%d'" % (remote_addr, base_port, child_idx))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # Allocate a new child</span><br><span style="color: hsl(120, 100%, 40%);">+ trx_child = FakeTRX(self.argv.trx_bind_addr, remote_addr, base_port,</span><br><span style="color: hsl(120, 100%, 40%);">+ child_idx = child_idx, pwr_meas = self.fake_pm)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.trx_list.add_trx(trx_child)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # Link a new 'child' with its 'parent'</span><br><span style="color: hsl(120, 100%, 40%);">+ trx_parent.child_trx_list.add_trx(trx_child)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> def run(self):</span><br><span> # Init shared clock generator</span><br><span> self.clck_gen = CLCKGen([])</span><br><span>@@ -280,49 +310,44 @@</span><br><span> self.fake_pm = FakePM(-120, -105, -75, -50)</span><br><span> </span><br><span> # Init TRX instance for BTS</span><br><span style="color: hsl(0, 100%, 40%);">- self.bts_trx = FakeTRX(self.argv.trx_bind_addr,</span><br><span style="color: hsl(0, 100%, 40%);">- self.argv.bts_addr, self.argv.bts_base_port,</span><br><span style="color: hsl(0, 100%, 40%);">- clck_gen = self.clck_gen)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.append_trx(self.argv.bts_addr, self.argv.bts_base_port)</span><br><span> </span><br><span> # Init TRX instance for BB</span><br><span style="color: hsl(0, 100%, 40%);">- self.bb_trx = FakeTRX(self.argv.trx_bind_addr,</span><br><span style="color: hsl(0, 100%, 40%);">- self.argv.bb_addr, self.argv.bb_base_port,</span><br><span style="color: hsl(0, 100%, 40%);">- pwr_meas = self.fake_pm)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.append_trx(self.argv.bb_addr, self.argv.bb_base_port)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # Additional transceivers (optional)</span><br><span style="color: hsl(120, 100%, 40%);">+ if self.argv.trx_list is not None:</span><br><span style="color: hsl(120, 100%, 40%);">+ for trx_def in self.argv.trx_list:</span><br><span style="color: hsl(120, 100%, 40%);">+ (addr, port, idx) = trx_def</span><br><span style="color: hsl(120, 100%, 40%);">+ self.append_child_trx(addr, port, idx)</span><br><span> </span><br><span> # Burst forwarding between transceivers</span><br><span style="color: hsl(0, 100%, 40%);">- self.burst_fwd = BurstForwarder()</span><br><span style="color: hsl(0, 100%, 40%);">- self.burst_fwd.add_trx(self.bts_trx)</span><br><span style="color: hsl(0, 100%, 40%);">- self.burst_fwd.add_trx(self.bb_trx)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.burst_fwd = BurstForwarder(self.trx_list)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # Compose list of to be monitored sockets</span><br><span style="color: hsl(120, 100%, 40%);">+ self.sock_list = []</span><br><span style="color: hsl(120, 100%, 40%);">+ for trx in self.trx_list:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.sock_list.append(trx.ctrl_if.sock)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.sock_list.append(trx.data_if.sock)</span><br><span> </span><br><span> log.info("Init complete")</span><br><span> </span><br><span> # Enter main loop</span><br><span> while True:</span><br><span style="color: hsl(0, 100%, 40%);">- socks = [self.bts_trx.ctrl_if.sock, self.bb_trx.ctrl_if.sock,</span><br><span style="color: hsl(0, 100%, 40%);">- self.bts_trx.data_if.sock, self.bb_trx.data_if.sock]</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> # Wait until we get any data on any socket</span><br><span style="color: hsl(0, 100%, 40%);">- r_event, w_event, x_event = select.select(socks, [], [])</span><br><span style="color: hsl(120, 100%, 40%);">+ r_event, _, _ = select.select(self.sock_list, [], [])</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- # Downlink: BTS -> BB</span><br><span style="color: hsl(0, 100%, 40%);">- if self.bts_trx.data_if.sock in r_event:</span><br><span style="color: hsl(0, 100%, 40%);">- msg = self.bts_trx.recv_data_msg()</span><br><span style="color: hsl(0, 100%, 40%);">- if msg is not None:</span><br><span style="color: hsl(0, 100%, 40%);">- self.burst_fwd.forward_msg(self.bts_trx, msg)</span><br><span style="color: hsl(120, 100%, 40%);">+ # Iterate over all transceivers</span><br><span style="color: hsl(120, 100%, 40%);">+ for trx in self.trx_list:</span><br><span style="color: hsl(120, 100%, 40%);">+ # DATA interface</span><br><span style="color: hsl(120, 100%, 40%);">+ if trx.data_if.sock in r_event:</span><br><span style="color: hsl(120, 100%, 40%);">+ msg = trx.recv_data_msg()</span><br><span style="color: hsl(120, 100%, 40%);">+ if msg is not None:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.burst_fwd.forward_msg(trx, msg)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- # Uplink: BB -> BTS</span><br><span style="color: hsl(0, 100%, 40%);">- if self.bb_trx.data_if.sock in r_event:</span><br><span style="color: hsl(0, 100%, 40%);">- msg = self.bb_trx.recv_data_msg()</span><br><span style="color: hsl(0, 100%, 40%);">- if msg is not None:</span><br><span style="color: hsl(0, 100%, 40%);">- self.burst_fwd.forward_msg(self.bb_trx, msg)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- # CTRL commands from BTS</span><br><span style="color: hsl(0, 100%, 40%);">- if self.bts_trx.ctrl_if.sock in r_event:</span><br><span style="color: hsl(0, 100%, 40%);">- self.bts_trx.ctrl_if.handle_rx()</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- # CTRL commands from BB</span><br><span style="color: hsl(0, 100%, 40%);">- if self.bb_trx.ctrl_if.sock in r_event:</span><br><span style="color: hsl(0, 100%, 40%);">- self.bb_trx.ctrl_if.handle_rx()</span><br><span style="color: hsl(120, 100%, 40%);">+ # CTRL interface</span><br><span style="color: hsl(120, 100%, 40%);">+ if trx.ctrl_if.sock in r_event:</span><br><span style="color: hsl(120, 100%, 40%);">+ trx.ctrl_if.handle_rx()</span><br><span> </span><br><span> def shutdown(self):</span><br><span> log.info("Shutting down...")</span><br><span>@@ -330,6 +355,25 @@</span><br><span> # Stop clock generator</span><br><span> self.clck_gen.stop()</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ # Parses a TRX definition of the following</span><br><span style="color: hsl(120, 100%, 40%);">+ # format: REMOTE_ADDR:BIND_PORT[/TRX_NUM]</span><br><span style="color: hsl(120, 100%, 40%);">+ # e.g. [2001:0db8:85a3:0000:0000:8a2e:0370:7334]:5700/5</span><br><span style="color: hsl(120, 100%, 40%);">+ # e.g. 127.0.0.1:5700 or 127.0.0.1:5700/1</span><br><span style="color: hsl(120, 100%, 40%);">+ @staticmethod</span><br><span style="color: hsl(120, 100%, 40%);">+ def trx_def(val):</span><br><span style="color: hsl(120, 100%, 40%);">+ try:</span><br><span style="color: hsl(120, 100%, 40%);">+ result = re.match("(.+):([0-9]+)(\/[0-9]+)?", val)</span><br><span style="color: hsl(120, 100%, 40%);">+ (addr, port, idx) = result.groups()</span><br><span style="color: hsl(120, 100%, 40%);">+ except:</span><br><span style="color: hsl(120, 100%, 40%);">+ raise argparse.ArgumentTypeError("Invalid TRX definition: %s" % val)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if idx is not None:</span><br><span style="color: hsl(120, 100%, 40%);">+ idx = int(idx[1:])</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ idx = 0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return (addr, int(port), idx)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> def parse_argv(self):</span><br><span> parser = argparse.ArgumentParser(prog = "fake_trx",</span><br><span> description = "Virtual Um-interface (fake transceiver)")</span><br><span>@@ -354,6 +398,12 @@</span><br><span> dest = "bb_base_port", type = int, default = 6700,</span><br><span> help = "Set BB base port number (default %(default)s)")</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ mtrx_group = parser.add_argument_group("Additional transceivers")</span><br><span style="color: hsl(120, 100%, 40%);">+ mtrx_group.add_argument("--trx",</span><br><span style="color: hsl(120, 100%, 40%);">+ metavar = "REMOTE_ADDR:BASE_PORT[/TRX_NUM]",</span><br><span style="color: hsl(120, 100%, 40%);">+ dest = "trx_list", type = self.trx_def, action = "append",</span><br><span style="color: hsl(120, 100%, 40%);">+ help = "Add a transceiver for BTS or MS (e.g. 127.0.0.1:5703)")</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> argv = parser.parse_args()</span><br><span> </span><br><span> # Make sure there is no overlap between ports</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/12325">change 12325</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/12325"/><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-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: Ibff31fb3a958a714c828d0dea7e87d47f778fd80 </div>
<div style="display:none"> Gerrit-Change-Number: 12325 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: Vadim Yanitskiy <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder (1000002) </div>
<div style="display:none"> Gerrit-Reviewer: Pau Espin Pedrol <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Vadim Yanitskiy <axilirator@gmail.com> </div>