<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>