<p>pespin has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-trx/+/19205">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Introduce rate counters to detect issues in received Dl bursts from TRXD<br><br>This ones together with rate counters already available in lower layers<br>allows to understand better the source of the problem with stalled tx<br>bursts.<br><br>Change-Id: Ia34f7e7d780ad1e12f24638a07f05fe91f2afea5<br>---<br>M CommonLibs/osmo_signal.h<br>M CommonLibs/trx_rate_ctr.cpp<br>M CommonLibs/trx_rate_ctr.h<br>M Transceiver52M/Transceiver.cpp<br>M Transceiver52M/Transceiver.h<br>5 files changed, 68 insertions(+), 9 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-trx refs/changes/05/19205/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/CommonLibs/osmo_signal.h b/CommonLibs/osmo_signal.h</span><br><span>index de17b1d..5cd90c6 100644</span><br><span>--- a/CommonLibs/osmo_signal.h</span><br><span>+++ b/CommonLibs/osmo_signal.h</span><br><span>@@ -61,4 +61,7 @@</span><br><span> struct trx_counters {</span><br><span> size_t chan;</span><br><span> unsigned int tx_stale_bursts; /* Amount of Tx bursts dropped to to arriving too late from TRXD */</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int tx_trxd_fn_repeated;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int tx_trxd_fn_outoforder;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int tx_trxd_fn_skipped;</span><br><span> };</span><br><span>diff --git a/CommonLibs/trx_rate_ctr.cpp b/CommonLibs/trx_rate_ctr.cpp</span><br><span>index 76aff7d..c74602a 100644</span><br><span>--- a/CommonLibs/trx_rate_ctr.cpp</span><br><span>+++ b/CommonLibs/trx_rate_ctr.cpp</span><br><span>@@ -103,6 +103,9 @@</span><br><span> { TRX_CTR_DEV_TX_DROP_EV, "tx_drop_events" },</span><br><span> { TRX_CTR_DEV_TX_DROP_SMPL, "tx_drop_samples" },</span><br><span> { TRX_CTR_TRX_TX_STALE_BURSTS, "tx_stale_bursts" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { TRX_CTR_TRX_TRXD_FN_REPEATED, "tx_trxd_fn_repeated" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { TRX_CTR_TRX_TRXD_FN_OUTOFORDER, "tx_trxd_fn_outoforder" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { TRX_CTR_TRX_TRXD_FN_SKIPPED, "tx_trxd_fn_skipped" },</span><br><span> { 0, NULL }</span><br><span> };</span><br><span> </span><br><span>@@ -114,6 +117,9 @@</span><br><span> [TRX_CTR_DEV_TX_DROP_EV] = { "device:tx_drop_events", "Number of times Tx samples were dropped by HW" },</span><br><span> [TRX_CTR_DEV_TX_DROP_SMPL] = { "device:tx_drop_samples", "Number of Tx samples dropped by HW" },</span><br><span> [TRX_CTR_TRX_TX_STALE_BURSTS] = { "trx:tx_stale_bursts", "Number of Tx burts dropped by TRX due to arriving too late" },</span><br><span style="color: hsl(120, 100%, 40%);">+ [TRX_CTR_TRX_TRXD_FN_REPEATED] = { "trx:tx_trxd_fn_repeated", "Number of Tx burts received from TRXD with repeated FN" },</span><br><span style="color: hsl(120, 100%, 40%);">+ [TRX_CTR_TRX_TRXD_FN_OUTOFORDER] = { "trx:tx_trxd_fn_outoforder","Number of Tx burts received from TRXD with a past FN" },</span><br><span style="color: hsl(120, 100%, 40%);">+ [TRX_CTR_TRX_TRXD_FN_SKIPPED] = { "trx:tx_trxd_fn_skipped", "Number of Tx burts potentially skipped due to FN jumps" },</span><br><span> };</span><br><span> </span><br><span> static const struct rate_ctr_group_desc trx_chan_ctr_group_desc = {</span><br><span>@@ -166,6 +172,12 @@</span><br><span> LOGCHAN(chan, DMAIN, INFO) << "rate_ctr update";</span><br><span> ctr = &rate_ctrs[chan]->ctr[TRX_CTR_TRX_TX_STALE_BURSTS];</span><br><span> rate_ctr_add(ctr, trx_ctrs_pending[chan].tx_stale_bursts - ctr->current);</span><br><span style="color: hsl(120, 100%, 40%);">+ ctr = &rate_ctrs[chan]->ctr[TRX_CTR_TRX_TRXD_FN_REPEATED];</span><br><span style="color: hsl(120, 100%, 40%);">+ rate_ctr_add(ctr, trx_ctrs_pending[chan].tx_trxd_fn_repeated - ctr->current);</span><br><span style="color: hsl(120, 100%, 40%);">+ ctr = &rate_ctrs[chan]->ctr[TRX_CTR_TRX_TRXD_FN_OUTOFORDER];</span><br><span style="color: hsl(120, 100%, 40%);">+ rate_ctr_add(ctr, trx_ctrs_pending[chan].tx_trxd_fn_outoforder - ctr->current);</span><br><span style="color: hsl(120, 100%, 40%);">+ ctr = &rate_ctrs[chan]->ctr[TRX_CTR_TRX_TRXD_FN_SKIPPED];</span><br><span style="color: hsl(120, 100%, 40%);">+ rate_ctr_add(ctr, trx_ctrs_pending[chan].tx_trxd_fn_skipped - ctr->current);</span><br><span> /* Mark as done */</span><br><span> trx_ctrs_pending[chan].chan = PENDING_CHAN_NONE;</span><br><span> }</span><br><span>diff --git a/CommonLibs/trx_rate_ctr.h b/CommonLibs/trx_rate_ctr.h</span><br><span>index 588ac2f..cef3c21 100644</span><br><span>--- a/CommonLibs/trx_rate_ctr.h</span><br><span>+++ b/CommonLibs/trx_rate_ctr.h</span><br><span>@@ -11,6 +11,9 @@</span><br><span> TRX_CTR_DEV_TX_DROP_EV,</span><br><span> TRX_CTR_DEV_TX_DROP_SMPL,</span><br><span> TRX_CTR_TRX_TX_STALE_BURSTS,</span><br><span style="color: hsl(120, 100%, 40%);">+ TRX_CTR_TRX_TRXD_FN_REPEATED,</span><br><span style="color: hsl(120, 100%, 40%);">+ TRX_CTR_TRX_TRXD_FN_OUTOFORDER,</span><br><span style="color: hsl(120, 100%, 40%);">+ TRX_CTR_TRX_TRXD_FN_SKIPPED,</span><br><span> };</span><br><span> </span><br><span> struct ctr_threshold {</span><br><span>diff --git a/Transceiver52M/Transceiver.cpp b/Transceiver52M/Transceiver.cpp</span><br><span>index 2ae5eda..01714db 100644</span><br><span>--- a/Transceiver52M/Transceiver.cpp</span><br><span>+++ b/Transceiver52M/Transceiver.cpp</span><br><span>@@ -52,6 +52,14 @@</span><br><span> /* Number of running values use in noise average */</span><br><span> #define NOISE_CNT 20</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dispatch_trx_rate_ctr_change(TransceiverState *state, unsigned int chan) {</span><br><span style="color: hsl(120, 100%, 40%);">+ thread_enable_cancel(false);</span><br><span style="color: hsl(120, 100%, 40%);">+ state->ctrs.chan = chan;</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_signal_dispatch(SS_DEVICE, S_TRX_COUNTER_CHANGE, &state->ctrs);</span><br><span style="color: hsl(120, 100%, 40%);">+ thread_enable_cancel(true);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> TransceiverState::TransceiverState()</span><br><span> : mRetrans(false), mNoiseLev(0.0), mNoises(NOISE_CNT), mPower(0.0)</span><br><span> {</span><br><span>@@ -437,12 +445,8 @@</span><br><span> delete burst;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (stale_bursts_changed) {</span><br><span style="color: hsl(0, 100%, 40%);">- thread_enable_cancel(false);</span><br><span style="color: hsl(0, 100%, 40%);">- state->ctrs.chan = i;</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_signal_dispatch(SS_DEVICE, S_TRX_COUNTER_CHANGE, &state->ctrs);</span><br><span style="color: hsl(0, 100%, 40%);">- thread_enable_cancel(true);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (stale_bursts_changed)</span><br><span style="color: hsl(120, 100%, 40%);">+ dispatch_trx_rate_ctr_change(state, i);</span><br><span> </span><br><span> TN = nowTime.TN();</span><br><span> modFN = nowTime.FN() % state->fillerModulus[TN];</span><br><span>@@ -461,7 +465,7 @@</span><br><span> }</span><br><span> </span><br><span> delete burst;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(120, 100%, 40%);">+ } //else { rate_counter() }</span><br><span> }</span><br><span> </span><br><span> mRadioInterface->driveTransmitRadio(bursts, zeros);</span><br><span>@@ -1001,6 +1005,7 @@</span><br><span> struct trxd_hdr_v01_dl *dl;</span><br><span> char buffer[sizeof(*dl) + EDGE_BURST_NBITS];</span><br><span> uint32_t fn;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t tn;</span><br><span> </span><br><span> // check data socket</span><br><span> msgLen = read(mDataSockets[chan], buffer, sizeof(buffer));</span><br><span>@@ -1029,6 +1034,7 @@</span><br><span> </span><br><span> /* Convert TDMA FN to the host endianness */</span><br><span> fn = osmo_load32be(&dl->common.fn);</span><br><span style="color: hsl(120, 100%, 40%);">+ tn = dl->common.tn;</span><br><span> </span><br><span> /* Make sure we support the received header format */</span><br><span> switch (dl->common.version) {</span><br><span>@@ -1044,14 +1050,45 @@</span><br><span> LOGCHAN(chan, DTRXDDL, DEBUG) << "Rx TRXD message (hdr_ver=" << unsigned(dl->common.version)</span><br><span> << "): fn=" << fn << ", tn=" << unsigned(dl->common.tn) << ", burst_len=" << burstLen;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ TransceiverState *state = &mStates[chan];</span><br><span style="color: hsl(120, 100%, 40%);">+ GSM::Time currTime = GSM::Time(fn, tn);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Verify proper FN order in DL stream */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (state->first_dl_fn_rcv[tn]) {</span><br><span style="color: hsl(120, 100%, 40%);">+ int32_t delta = GSM::FNDelta(currTime.FN(), state->last_dl_time_rcv[tn].FN());</span><br><span style="color: hsl(120, 100%, 40%);">+ if (delta == 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* usual expected scenario, continue code flow */</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (delta == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGCHAN(chan, DTRXDDL, NOTICE) << "Rx TRXD msg with repeated FN " << currTime;</span><br><span style="color: hsl(120, 100%, 40%);">+ state->ctrs.tx_trxd_fn_repeated++;</span><br><span style="color: hsl(120, 100%, 40%);">+ dispatch_trx_rate_ctr_change(state, chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ return true;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (delta < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGCHAN(chan, DTRXDDL, NOTICE) << "Rx TRXD msg with previous FN " << currTime</span><br><span style="color: hsl(120, 100%, 40%);">+ << " vs last " << state->last_dl_time_rcv[tn];</span><br><span style="color: hsl(120, 100%, 40%);">+ state->ctrs.tx_trxd_fn_outoforder++;</span><br><span style="color: hsl(120, 100%, 40%);">+ dispatch_trx_rate_ctr_change(state, chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Allow adding radio vector below, since it gets sorted in the queue */</span><br><span style="color: hsl(120, 100%, 40%);">+ } else { /* some FN was lost in the middle */</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGCHAN(chan, DTRXDDL, NOTICE) << "Rx TRXD msg with future FN " << currTime</span><br><span style="color: hsl(120, 100%, 40%);">+ << " vs last " << state->last_dl_time_rcv[tn]</span><br><span style="color: hsl(120, 100%, 40%);">+ << ", " << delta - 1 << " FN lost";</span><br><span style="color: hsl(120, 100%, 40%);">+ state->ctrs.tx_trxd_fn_skipped += delta - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ dispatch_trx_rate_ctr_change(state, chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (delta > 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ state->last_dl_time_rcv[tn] = currTime;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else { /* Initial check, simply store state */</span><br><span style="color: hsl(120, 100%, 40%);">+ state->first_dl_fn_rcv[tn] = true;</span><br><span style="color: hsl(120, 100%, 40%);">+ state->last_dl_time_rcv[tn] = currTime;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> BitVector newBurst(burstLen);</span><br><span> BitVector::iterator itr = newBurst.begin();</span><br><span> uint8_t *bufferItr = dl->soft_bits;</span><br><span> while (itr < newBurst.end())</span><br><span> *itr++ = *bufferItr++;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- GSM::Time currTime = GSM::Time(fn, dl->common.tn);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> addRadioVector(chan, newBurst, dl->tx_att, currTime);</span><br><span> </span><br><span> return true;</span><br><span>diff --git a/Transceiver52M/Transceiver.h b/Transceiver52M/Transceiver.h</span><br><span>index 7ce5fa2..52748c1 100644</span><br><span>--- a/Transceiver52M/Transceiver.h</span><br><span>+++ b/Transceiver52M/Transceiver.h</span><br><span>@@ -86,6 +86,10 @@</span><br><span> </span><br><span> /* counters */</span><br><span> struct trx_counters ctrs;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Used to keep track of lost and out of order frames */</span><br><span style="color: hsl(120, 100%, 40%);">+ bool first_dl_fn_rcv[8];</span><br><span style="color: hsl(120, 100%, 40%);">+ GSM::Time last_dl_time_rcv[8];</span><br><span> };</span><br><span> </span><br><span> /** The Transceiver class, responsible for physical layer of basestation */</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-trx/+/19205">change 19205</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-trx/+/19205"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: osmo-trx </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ia34f7e7d780ad1e12f24638a07f05fe91f2afea5 </div>
<div style="display:none"> Gerrit-Change-Number: 19205 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>