<p>Harald Welte <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/10309">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Harald Welte: Looks good to me, but someone else must approve
Pau Espin Pedrol: Looks good to me, approved
Jenkins Builder: Verified
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">common/scheduler.c: track TDMA frame loss per logical channels<br><br>This change modifies the logic of TDMA frame loss tracking. To<br>be more precise, the tracking logic was moved from per timeslot<br>level to per logical channel level, what makes OsmoBTS more<br>accurate in its measurements.<br><br>But before getting into details, it's important to clarify some<br>things about the Uplink burst processing in transceiver (OsmoTRX).<br>If an Uplink burst is detected, OsmoTRX demodulates it and sends<br>to OsmoBTS. If nothing is detected on a particular timeslot,<br>OsmoTRX will do nothing. In other words, it will not<br>notify OsmoBTS about this.<br><br>Meanwhile, there are usually a few logical channels mapped to a<br>single TDMA timeslot. Let's use SDCCH8 channel configuration as<br>an example (simplified layout):<br><br> /* SDCCH/8 (ss=0), subscriber A (active) */<br> { TRXC_SDCCH8_0, bid=0 },<br> { TRXC_SDCCH8_0, bid=1 },<br> { TRXC_SDCCH8_0, bid=2 },<br> { TRXC_SDCCH8_0, bid=3 }, // <-- last_fn=X<br><br> /* SDCCH/8 (ss=1), subscriber B (inactive) */<br> { TRXC_SDCCH8_1, bid=0 },<br> { TRXC_SDCCH8_1, bid=1 },<br> { TRXC_SDCCH8_1, bid=2 },<br> { TRXC_SDCCH8_1, bid=3 },<br><br> /* SDCCH/8 (ss=2), subscriber C (active) */<br> { TRXC_SDCCH8_2, bid=0 }, // <-- current_fn=X+5<br> { TRXC_SDCCH8_2, bid=1 },<br> { TRXC_SDCCH8_2, bid=2 },<br> { TRXC_SDCCH8_2, bid=3 },<br><br>SDCCH8 has 8 sub-slots, so up to 8 subscribers can use a single<br>timeslot. Let's imagine there are three subscribers: A, B, and C.<br>Both A and C are active subscribers, i.e. they are continuously<br>transmitting UL bursts, while B is not using ss=1 anymore.<br><br>The original way of TDMA frame loss tracking was the following:<br><br> - when an UL burst is received, store it's frame number in<br> the timeslot state structure (last_fn);<br><br> - when the next UL burst is received on same timeslot, compute<br> how many frames elapsed since the last_fn;<br><br> - if elapsed = (current_fn - last_fn) is lower than 10, then<br> iterate from (last_fn + 1) until the current_fn and send<br> dummy zero-filled bursts to the higher layers;<br><br> - otherwise (elapsed > 10), process the current burst,<br> and do nothing :/<br><br>According to our example, subscriber A is sending 4 bursts, then<br>nobody is sending anything, and then subscriber C is sending<br>4 bursts. So, there is a 4 frames long gap between the both<br>transmissions, which is being substituted by dummy bursts. But,<br>as the logical channel on ss=1 is not active, they are dropped.<br><br>This is not that scary, but the current algorithm produces lots<br>of false-positives, and moreover is not able to track real frame<br>drops in longer periods (i.e. >10). So, tracking the frame loss<br>per individual logical channels makes much more sense.<br><br>Let's finally drop this hackish 'while (42) { ... }', and track<br>the amount of lost / received TDMA frames (bursts) individually<br>per logical channels. Let's also use the multiframe period as<br>the loss detection period, instead of hardcoded 10. And finally,<br>let's print more informative debug messages.<br><br>Also, it makes sense to use the amount of lost / received bursts<br>during the calculation of the measurement reports, instead of<br>sending dummy bursts, but let's do this separately.<br><br>Change-Id: I70d05b67a35ddcbdd1b6394dbd7198404a440e76<br>Related: OS#3428<br>---<br>M include/osmo-bts/scheduler.h<br>M src/common/scheduler.c<br>2 files changed, 142 insertions(+), 65 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h</span><br><span>index 32d6e91..f9d9962 100644</span><br><span>--- a/include/osmo-bts/scheduler.h</span><br><span>+++ b/include/osmo-bts/scheduler.h</span><br><span>@@ -80,6 +80,9 @@</span><br><span> </span><br><span> /* loss detection */</span><br><span> uint8_t lost_frames; /* how many L2 frames were lost */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t last_tdma_fn; /* last processed TDMA frame number */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t proc_tdma_fs; /* how many TDMA frames were processed */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t lost_tdma_fs; /* how many TDMA frames were lost */</span><br><span> </span><br><span> /* mode */</span><br><span> uint8_t rsl_cmode, tch_mode; /* mode for TCH channels */</span><br><span>@@ -124,7 +127,6 @@</span><br><span> </span><br><span> struct l1sched_ts {</span><br><span> uint8_t mf_index; /* selected multiframe index */</span><br><span style="color: hsl(0, 100%, 40%);">- uint32_t mf_last_fn; /* last received frame number */</span><br><span> uint8_t mf_period; /* period of multiframe */</span><br><span> const struct trx_sched_frame *mf_frames; /* pointer to frame layout */</span><br><span> </span><br><span>diff --git a/src/common/scheduler.c b/src/common/scheduler.c</span><br><span>index 65ece7f..f705ddf 100644</span><br><span>--- a/src/common/scheduler.c</span><br><span>+++ b/src/common/scheduler.c</span><br><span>@@ -222,7 +222,6 @@</span><br><span> struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);</span><br><span> </span><br><span> l1ts->mf_index = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- l1ts->mf_last_fn = 0;</span><br><span> INIT_LLIST_HEAD(&l1ts->dl_prims);</span><br><span> for (i = 0; i < ARRAY_SIZE(l1ts->chan_state); i++) {</span><br><span> struct l1sched_chan_state *chan_state;</span><br><span>@@ -853,8 +852,115 @@</span><br><span> return bits;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define TDMA_FN_SUM(a, b) \</span><br><span style="color: hsl(120, 100%, 40%);">+ ((a + GSM_HYPERFRAME + b) % GSM_HYPERFRAME)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define TDMA_FN_SUB(a, b) \</span><br><span style="color: hsl(120, 100%, 40%);">+ ((a + GSM_HYPERFRAME - b) % GSM_HYPERFRAME)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int trx_sched_calc_frame_loss(struct l1sched_trx *l1t,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct l1sched_chan_state *l1cs, uint8_t tn, uint32_t fn)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct trx_sched_frame *frame_head;</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct trx_sched_frame *frame;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct l1sched_ts *l1ts;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t elapsed_fs;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t offset, i;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t fn_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%);">+ * When a channel is just activated, the MS needs some time</span><br><span style="color: hsl(120, 100%, 40%);">+ * to synchronize and start burst transmission,</span><br><span style="color: hsl(120, 100%, 40%);">+ * so let's wait until the first UL burst...</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (l1cs->proc_tdma_fs == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Get current TDMA frame info */</span><br><span style="color: hsl(120, 100%, 40%);">+ l1ts = l1sched_trx_get_ts(l1t, tn);</span><br><span style="color: hsl(120, 100%, 40%);">+ offset = fn % l1ts->mf_period;</span><br><span style="color: hsl(120, 100%, 40%);">+ frame_head = l1ts->mf_frames + offset;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Not applicable for some logical channels */</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (frame_head->ul_chan) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case TRXC_IDLE:</span><br><span style="color: hsl(120, 100%, 40%);">+ case TRXC_RACH:</span><br><span style="color: hsl(120, 100%, 40%);">+ case TRXC_PDTCH:</span><br><span style="color: hsl(120, 100%, 40%);">+ case TRXC_PTCCH:</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* No applicable if we are waiting for handover RACH */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (l1cs->ho_rach_detect)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</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%);">+ /* How many frames elapsed since the last one? */</span><br><span style="color: hsl(120, 100%, 40%);">+ elapsed_fs = TDMA_FN_SUB(fn, l1cs->last_tdma_fn);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (elapsed_fs > l1ts->mf_period) { /* Too many! */</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGL1S(DL1P, LOGL_ERROR, l1t, tn, frame_head->ul_chan, fn,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Too many (>%u) contiguous TDMA frames=%u elapsed "</span><br><span style="color: hsl(120, 100%, 40%);">+ "since the last processed fn=%u\n", l1ts->mf_period,</span><br><span style="color: hsl(120, 100%, 40%);">+ elapsed_fs, l1cs->last_tdma_fn);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FIXME: how should this affect the measurements? */</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</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%);">+ * There are several TDMA frames between the last processed</span><br><span style="color: hsl(120, 100%, 40%);">+ * frame and currently received one. Let's walk through this</span><br><span style="color: hsl(120, 100%, 40%);">+ * path and count potentially lost frames, i.e. for which</span><br><span style="color: hsl(120, 100%, 40%);">+ * we didn't receive the corresponsing UL bursts.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Start counting from the last_fn + 1.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 1; i < elapsed_fs; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ fn_i = TDMA_FN_SUM(l1cs->last_tdma_fn, i);</span><br><span style="color: hsl(120, 100%, 40%);">+ offset = fn_i % l1ts->mf_period;</span><br><span style="color: hsl(120, 100%, 40%);">+ frame = l1ts->mf_frames + offset;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (frame->ul_chan == frame_head->ul_chan)</span><br><span style="color: hsl(120, 100%, 40%);">+ l1cs->lost_tdma_fs++;</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%);">+ if (l1cs->lost_tdma_fs > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, frame_head->ul_chan, fn,</span><br><span style="color: hsl(120, 100%, 40%);">+ "At least %u TDMA frames were lost since the last "</span><br><span style="color: hsl(120, 100%, 40%);">+ "processed fn=%u\n", l1cs->lost_tdma_fs, l1cs->last_tdma_fn);</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%);">+ * HACK: substitute lost bursts by zero-filled ones</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Instead of doing this, it makes sense to use the</span><br><span style="color: hsl(120, 100%, 40%);">+ * amount of lost frames in measurement calculations.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ static sbit_t zero_burst[GSM_BURST_LEN] = { 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+ trx_sched_ul_func *func;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 1; i < elapsed_fs; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ fn_i = TDMA_FN_SUM(l1cs->last_tdma_fn, i);</span><br><span style="color: hsl(120, 100%, 40%);">+ offset = fn_i % l1ts->mf_period;</span><br><span style="color: hsl(120, 100%, 40%);">+ frame = l1ts->mf_frames + offset;</span><br><span style="color: hsl(120, 100%, 40%);">+ func = trx_chan_desc[frame->ul_chan].ul_fn;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (frame->ul_chan != frame_head->ul_chan)</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, frame->ul_chan, fn,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Substituting lost TDMA frame=%u by all-zero "</span><br><span style="color: hsl(120, 100%, 40%);">+ "dummy burst\n", fn_i);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ func(l1t, tn, fn_i, frame->ul_chan, frame->ul_bid,</span><br><span style="color: hsl(120, 100%, 40%);">+ zero_burst, GSM_BURST_LEN, -128, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ l1cs->lost_tdma_fs--;</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 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* process uplink burst */</span><br><span style="color: hsl(0, 100%, 40%);">-int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t current_fn,</span><br><span style="color: hsl(120, 100%, 40%);">+int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,</span><br><span> sbit_t *bits, uint16_t nbits, int8_t rssi, int16_t toa256)</span><br><span> {</span><br><span> struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);</span><br><span>@@ -863,82 +969,51 @@</span><br><span> uint8_t offset, period, bid;</span><br><span> trx_sched_ul_func *func;</span><br><span> enum trx_chan_type chan;</span><br><span style="color: hsl(0, 100%, 40%);">- uint32_t fn, elapsed;</span><br><span> </span><br><span> if (!l1ts->mf_index)</span><br><span> return -EINVAL;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* calculate how many frames have been elapsed */</span><br><span style="color: hsl(0, 100%, 40%);">- elapsed = (current_fn + GSM_HYPERFRAME - l1ts->mf_last_fn) % GSM_HYPERFRAME;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* get frame from multiframe */</span><br><span style="color: hsl(120, 100%, 40%);">+ period = l1ts->mf_period;</span><br><span style="color: hsl(120, 100%, 40%);">+ offset = fn % period;</span><br><span style="color: hsl(120, 100%, 40%);">+ frame = l1ts->mf_frames + offset;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* start counting from last fn + 1, but only if not too many fn have</span><br><span style="color: hsl(0, 100%, 40%);">- * been elapsed */</span><br><span style="color: hsl(0, 100%, 40%);">- if (elapsed < 10) {</span><br><span style="color: hsl(0, 100%, 40%);">- fn = (l1ts->mf_last_fn + 1) % GSM_HYPERFRAME;</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPFN(DL1P, LOGL_NOTICE, current_fn,</span><br><span style="color: hsl(0, 100%, 40%);">- "Too many contiguous elapsed fn, dropping %u\n", elapsed);</span><br><span style="color: hsl(0, 100%, 40%);">- fn = current_fn;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(120, 100%, 40%);">+ chan = frame->ul_chan;</span><br><span style="color: hsl(120, 100%, 40%);">+ bid = frame->ul_bid;</span><br><span style="color: hsl(120, 100%, 40%);">+ l1cs = &l1ts->chan_state[chan];</span><br><span style="color: hsl(120, 100%, 40%);">+ func = trx_chan_desc[chan].ul_fn;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- while (42) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* get frame from multiframe */</span><br><span style="color: hsl(0, 100%, 40%);">- period = l1ts->mf_period;</span><br><span style="color: hsl(0, 100%, 40%);">- offset = fn % period;</span><br><span style="color: hsl(0, 100%, 40%);">- frame = l1ts->mf_frames + offset;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* check if channel is active */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!trx_chan_desc[chan].auto_active && !l1cs->active)</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- chan = frame->ul_chan;</span><br><span style="color: hsl(0, 100%, 40%);">- bid = frame->ul_bid;</span><br><span style="color: hsl(0, 100%, 40%);">- func = trx_chan_desc[chan].ul_fn;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* omit bursts which have no handler, like IDLE bursts */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!func)</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- l1cs = &l1ts->chan_state[chan];</span><br><span style="color: hsl(120, 100%, 40%);">+ /* calculate how many TDMA frames were potentially lost */</span><br><span style="color: hsl(120, 100%, 40%);">+ trx_sched_calc_frame_loss(l1t, l1cs, tn, fn);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* check if channel is active */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!trx_chan_desc[chan].auto_active && !l1cs->active)</span><br><span style="color: hsl(0, 100%, 40%);">- goto next_frame;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* update TDMA frame counters */</span><br><span style="color: hsl(120, 100%, 40%);">+ l1cs->last_tdma_fn = fn;</span><br><span style="color: hsl(120, 100%, 40%);">+ l1cs->proc_tdma_fs++;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* omit bursts which have no handler, like IDLE bursts */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!func)</span><br><span style="color: hsl(0, 100%, 40%);">- goto next_frame;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* decrypt */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bits && l1cs->ul_encr_algo) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ubit_t ks[114];</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* put burst to function */</span><br><span style="color: hsl(0, 100%, 40%);">- if (fn == current_fn) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* decrypt */</span><br><span style="color: hsl(0, 100%, 40%);">- if (bits && l1cs->ul_encr_algo) {</span><br><span style="color: hsl(0, 100%, 40%);">- ubit_t ks[114];</span><br><span style="color: hsl(0, 100%, 40%);">- int i;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_a5(l1cs->ul_encr_algo,</span><br><span style="color: hsl(0, 100%, 40%);">- l1cs->ul_encr_key,</span><br><span style="color: hsl(0, 100%, 40%);">- fn, NULL, ks);</span><br><span style="color: hsl(0, 100%, 40%);">- for (i = 0; i < 57; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (ks[i])</span><br><span style="color: hsl(0, 100%, 40%);">- bits[i + 3] = - bits[i + 3];</span><br><span style="color: hsl(0, 100%, 40%);">- if (ks[i + 57])</span><br><span style="color: hsl(0, 100%, 40%);">- bits[i + 88] = - bits[i + 88];</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- func(l1t, tn, fn, chan, bid, bits, nbits, rssi, toa256);</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (chan != TRXC_RACH && !l1cs->ho_rach_detect) {</span><br><span style="color: hsl(0, 100%, 40%);">- sbit_t spare[GSM_BURST_LEN];</span><br><span style="color: hsl(0, 100%, 40%);">- memset(spare, 0, GSM_BURST_LEN);</span><br><span style="color: hsl(0, 100%, 40%);">- /* We missed a couple of frame numbers (system overload?) and are now</span><br><span style="color: hsl(0, 100%, 40%);">- * substituting some zero-filled bursts for those bursts we missed */</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPFN(DL1P, LOGL_ERROR, fn, "Substituting all-zero burst (current_fn=%u, "</span><br><span style="color: hsl(0, 100%, 40%);">- "elapsed=%u\n", current_fn, elapsed);</span><br><span style="color: hsl(0, 100%, 40%);">- func(l1t, tn, fn, chan, bid, spare, GSM_BURST_LEN, -128, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_a5(l1cs->ul_encr_algo, l1cs->ul_encr_key, fn, NULL, ks);</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < 57; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ks[i])</span><br><span style="color: hsl(120, 100%, 40%);">+ bits[i + 3] = - bits[i + 3];</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ks[i + 57])</span><br><span style="color: hsl(120, 100%, 40%);">+ bits[i + 88] = - bits[i + 88];</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-next_frame:</span><br><span style="color: hsl(0, 100%, 40%);">- /* reached current fn */</span><br><span style="color: hsl(0, 100%, 40%);">- if (fn == current_fn)</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- fn = (fn + 1) % GSM_HYPERFRAME;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- l1ts->mf_last_fn = fn;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* put burst to function */</span><br><span style="color: hsl(120, 100%, 40%);">+ func(l1t, tn, fn, chan, bid, bits, nbits, rssi, toa256);</span><br><span> </span><br><span> return 0;</span><br><span> }</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/10309">change 10309</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/10309"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: osmo-bts </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I70d05b67a35ddcbdd1b6394dbd7198404a440e76 </div>
<div style="display:none"> Gerrit-Change-Number: 10309 </div>
<div style="display:none"> Gerrit-PatchSet: 5 </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>