kirr has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmocom-bb/+/39328?usp=email )
Change subject: [WIP] Revert "Revert "trx_toolkit/transceiver.py: implement the
transmit burst queue""
......................................................................
[WIP] Revert "Revert "trx_toolkit/transceiver.py: implement the transmit burst
queue""
This reverts commit d4ed09df57b3461470af501e9687ddd80eb78838,
reinstating tx queue into fake_trx.
It is ok to do so because, as explained in the previous patch, the
reason for GSM clock jitter problem was timing error accumulation in
CLCKgen, not problems with py threading.Event.
Note: this restores original tx queue implementation basically as-is
with only resolve minor conflicts during the revert. The original tx
queue implementation wastes CPU cycles though because it linearly scans
the whole tx queue at every TDMA frame. If that CPU usage becomes a real
problem it should be straightforward to fix by reworking tx queue to use
priority queue instead of unordered array via heapq module from standard
library. See
https://docs.python.org/3/library/heapq.html for details.
(WIP because I did not tested this patch fully as I could not yet
organize a working fake_trx setup due to not fully done homework yet)
Related: OS#4658, OS#6672
Change-Id: I41291708effdd2c767be680fff22ffbd9a56815e
---
M src/target/trx_toolkit/fake_trx.py
M src/target/trx_toolkit/transceiver.py
2 files changed, 72 insertions(+), 3 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/28/39328/1
diff --git a/src/target/trx_toolkit/fake_trx.py b/src/target/trx_toolkit/fake_trx.py
index 0daecb4..21bd189 100755
--- a/src/target/trx_toolkit/fake_trx.py
+++ b/src/target/trx_toolkit/fake_trx.py
@@ -398,6 +398,8 @@
# Init shared clock generator
self.clck_gen = CLCKGen([])
+ # This method will be called on each TDMA frame
+ self.clck_gen.clck_handler = self.clck_handler
# Power measurement emulation
# Noise: -120 .. -105
@@ -463,14 +465,18 @@
for trx in self.trx_list.trx_list:
# DATA interface
if trx.data_if.sock in r_event:
- msg = trx.recv_data_msg()
- if msg is not None:
- self.burst_fwd.forward_msg(trx, msg)
+ trx.recv_data_msg()
# CTRL interface
if trx.ctrl_if.sock in r_event:
trx.ctrl_if.handle_rx()
+ # This method will be called by the clock thread
+ def clck_handler(self, fn):
+ # We assume that this list is immutable at run-time
+ for trx in self.trx_list.trx_list:
+ trx.clck_tick(self.burst_fwd, fn)
+
def shutdown(self):
log.info("Shutting down...")
diff --git a/src/target/trx_toolkit/transceiver.py
b/src/target/trx_toolkit/transceiver.py
index ffd18ab..4e1cb87 100644
--- a/src/target/trx_toolkit/transceiver.py
+++ b/src/target/trx_toolkit/transceiver.py
@@ -19,6 +19,7 @@
# GNU General Public License for more details.
import logging as log
+import threading
from ctrl_if_trx import CTRLInterfaceTRX
from data_if import DATAInterface
@@ -109,6 +110,37 @@
Transceiver and all its timeslots, so using in for the BTS side
does not make any sense (imagine BCCH hopping together with DCCH).
+ == The transmit burst queue
+
+ According to 3GPP 45.002, the time difference between Uplink and
+ Downlink corresponds to three TDMA timeslot periods. However,
+ in general the L1 implementations (such as osmo-bts-trx and trxcon)
+ never schedule to be transmitted bursts for the current TDMA frame
+ immediately. Instead, they are being scheduled prematurely.
+
+ The rationale is that both transceiver and the L1 implementation
+ are separete processes that are not perfectly synchronized in time.
+ Moreover, the transceiver needs some time to prepare a burst for
+ transmission. This is why the time difference between Uplink and
+ Downlink is actually much higher on practice (20 TDMA frame periods
+ by default, at the moment of writing this patch).
+
+ In order to reflect that delay in a virtual environment, this
+ implementation, just like a normal transceiver (e.g. osmo-trx),
+ queues all to be transmitted (L12TRX) bursts, so hey remain in
+ the transmit queue until the appropriate time of transmission.
+
+ The API user is supposed to call recv_data_msg() in order to obtain
+ a L12TRX message on the TRXD (data) inteface, so it gets queued by
+ this function. Then, to ensure the timeous transmission, the user
+ of this implementation needs to call clck_tick() on each TDMA
+ frame. Both functions are thread-safe (queue mutex).
+
+ In a multi-trx configuration, the use of queue additionally ensures
+ proper burst aggregation on multiple TRXD connections, so all L12TRX
+ messages are guaranteed to be sent in the right order, i.e. with
+ monolithically-increasing TDMA frame numbers.
+
"""
def __init__(self, bind_addr, remote_addr, base_port, **kwargs):
@@ -161,6 +193,10 @@
# List of child transceivers
self.child_trx_list = TRXList()
+ # Tx (L12TRX) burst queue and mutex
+ self._tx_queue_lock = threading.Lock()
+ self._tx_queue = []
+
def __str__(self):
desc = "%s:%d" % (self.remote_addr, self.base_port)
if self.child_idx > 0:
@@ -220,6 +256,7 @@
for trx in trx_list:
trx.running = poweron
if not poweron:
+ trx.tx_queue_clear()
trx.disable_fh()
# Trigger clock generator if required
@@ -251,8 +288,34 @@
"is not running => dropping..." % (self, msg.desc_hdr()))
return None
+ # Enque the message, it will be sent later
+ self.tx_queue_append(msg)
return msg
def handle_data_msg(self, msg):
# TODO: make legacy mode configurable (via argv?)
self.data_if.send_msg(msg, legacy = True)
+
+ def tx_queue_append(self, msg):
+ with self._tx_queue_lock:
+ self._tx_queue.append(msg)
+
+ def tx_queue_clear(self):
+ with self._tx_queue_lock:
+ self._tx_queue.clear()
+
+ def clck_tick(self, fwd, fn):
+ if not self.running:
+ return
+
+ self._tx_queue_lock.acquire()
+
+ for msg in self._tx_queue:
+ if msg.fn == fn:
+ fwd.forward_msg(self, msg)
+ elif msg.fn < fn:
+ log.warning("(%s) Stale TRXD message (fn=%u): %s"
+ % (self, fn, msg.desc_hdr()))
+
+ self._tx_queue = [msg for msg in self._tx_queue if msg.fn > fn]
+ self._tx_queue_lock.release()
--
To view, visit
https://gerrit.osmocom.org/c/osmocom-bb/+/39328?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-Change-Id: I41291708effdd2c767be680fff22ffbd9a56815e
Gerrit-Change-Number: 39328
Gerrit-PatchSet: 1
Gerrit-Owner: kirr <kirr(a)nexedi.com>
Gerrit-CC: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-CC: osmith <osmith(a)sysmocom.de>
Gerrit-CC: pespin <pespin(a)sysmocom.de>