<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/libosmo-abis/+/19504">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  laforge: Looks good to me, approved
  Jenkins Builder: Verified

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">trau_frame: Introduce support for Downlink Time Alignment<br><br>In the uplink direction, we provide osmo_trau_frame_dl_ta_us()<br>to determine the time alignment as requested by the CCU in the BTS.<br><br>In the downlink direction, the TRAU frame encoder will perform<br>time alignment as requested by the user in osmo_trau_frame.dl_ta_usec.<br><br>Change-Id: I3981becafc56c9a50119b9ba6bf67aa0391cc76e<br>---<br>M include/osmocom/trau/trau_frame.h<br>M src/trau/trau_frame.c<br>2 files changed, 134 insertions(+), 40 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/trau/trau_frame.h b/include/osmocom/trau/trau_frame.h</span><br><span>index 6784d1f..5f1d708 100644</span><br><span>--- a/include/osmocom/trau/trau_frame.h</span><br><span>+++ b/include/osmocom/trau/trau_frame.h</span><br><span>@@ -110,6 +110,9 @@</span><br><span>   enum osmo_trau_frame_type type;</span><br><span>      enum osmo_trau_frame_direction dir;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+       /* timing alignment: 0 = no change; negative: less bits; positive: more bits */</span><br><span style="color: hsl(120, 100%, 40%);">+       int dl_ta_usec;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>    ubit_t c_bits[MAX_C_BITS];</span><br><span>   ubit_t d_bits[MAX_D_BITS];</span><br><span>   ubit_t t_bits[MAX_T_BITS];</span><br><span>@@ -142,5 +145,7 @@</span><br><span>  *  \return number of bits encoded */</span><br><span> int osmo_trau_frame_encode(ubit_t *bits, size_t n_bits, const struct osmo_trau_frame *fr);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Determine the time alignment in us requested by CCU in a UL frame */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_trau_frame_dl_ta_us(const struct osmo_trau_frame *fr);</span><br><span> </span><br><span> /* }@ */</span><br><span>diff --git a/src/trau/trau_frame.c b/src/trau/trau_frame.c</span><br><span>index a57d642..ea63938 100644</span><br><span>--- a/src/trau/trau_frame.c</span><br><span>+++ b/src/trau/trau_frame.c</span><br><span>@@ -74,6 +74,14 @@</span><br><span>  * New API; introduced in 2020 for use by osmo-mgw</span><br><span>  *********************************************************************************/</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* Bits C21..C22 (16k) or C4..C5 (8k) */</span><br><span style="color: hsl(120, 100%, 40%);">+enum ts48060_amr_frame_classification {</span><br><span style="color: hsl(120, 100%, 40%);">+      TS48060_AMR_FC_SPEECH_GOOD      = 0x3,</span><br><span style="color: hsl(120, 100%, 40%);">+        TS48060_AMR_FC_SPEECH_DEGRADED  = 0x2,</span><br><span style="color: hsl(120, 100%, 40%);">+        TS48060_AMR_FC_SPEECH_BAD       = 0x1,</span><br><span style="color: hsl(120, 100%, 40%);">+        TS48060_AMR_FC_NO_SPEECH        = 0x0,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* 16k sub-slots */</span><br><span> static const ubit_t ft_fr_up_bits[5] =           { 0, 0, 0, 1, 0 };</span><br><span> static const ubit_t ft_fr_down_bits[5] =  { 1, 1, 1, 0, 0 };</span><br><span>@@ -110,19 +118,125 @@</span><br><span> #define T16_500us        8       /* 500 us = 8 bits */</span><br><span> #define T16_250us      4       /* 250 us = 4 bits */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define T8_250us     2       /* 250 us = 2 bits */</span><br><span style="color: hsl(120, 100%, 40%);">+#define T8_125us 1       /* 125 us = 1 bits */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* How many 16k bits to delay / advance (TS 48.060 Section 5.5.1.1.1) */</span><br><span style="color: hsl(0, 100%, 40%);">-static int fr_efr_alignment_bitcount(uint8_t c6_11)</span><br><span style="color: hsl(120, 100%, 40%);">+static int trau_frame_16_ta_us(uint8_t c6_11)</span><br><span> {</span><br><span>   if (c6_11 <= 0x27)</span><br><span style="color: hsl(0, 100%, 40%);">-           return c6_11 * T16_500us;       /* delay frame N x 500us */</span><br><span style="color: hsl(120, 100%, 40%);">+           return c6_11 * 500;     /* delay frame N x 500us */</span><br><span>  else if (c6_11 == 0x3e)</span><br><span style="color: hsl(0, 100%, 40%);">-         return T16_250us;               /* delay frame 250us */</span><br><span style="color: hsl(120, 100%, 40%);">+               return 250;             /* delay frame 250us */</span><br><span>      else if (c6_11 == 0x3f)</span><br><span style="color: hsl(0, 100%, 40%);">-         return -T16_250us;              /* advance frame 250us */</span><br><span style="color: hsl(120, 100%, 40%);">+             return -250;    /* advance frame 250us */</span><br><span>    else</span><br><span>                 return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* How many 8k bits to delay / advance (TS 48.061 Table 6.1) */</span><br><span style="color: hsl(120, 100%, 40%);">+static int trau_frame_8_ta_us(uint8_t c6_8)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   /* TA2..TA1..TA0 == C6..C7..C8 */</span><br><span style="color: hsl(120, 100%, 40%);">+     switch (c6_8) {</span><br><span style="color: hsl(120, 100%, 40%);">+       case 0x7:</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     case 0x6:</span><br><span style="color: hsl(120, 100%, 40%);">+             return -250;</span><br><span style="color: hsl(120, 100%, 40%);">+  case 0x5:</span><br><span style="color: hsl(120, 100%, 40%);">+             return 250;</span><br><span style="color: hsl(120, 100%, 40%);">+   case 0x3:</span><br><span style="color: hsl(120, 100%, 40%);">+             return 500;</span><br><span style="color: hsl(120, 100%, 40%);">+   case 0x4:</span><br><span style="color: hsl(120, 100%, 40%);">+             return 1000;</span><br><span style="color: hsl(120, 100%, 40%);">+  case 0x2:</span><br><span style="color: hsl(120, 100%, 40%);">+             return 2000;</span><br><span style="color: hsl(120, 100%, 40%);">+  case 0x1:</span><br><span style="color: hsl(120, 100%, 40%);">+             return 6000;</span><br><span style="color: hsl(120, 100%, 40%);">+  case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+               return 9000;</span><br><span style="color: hsl(120, 100%, 40%);">+  default:</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Determine the time alignment in us requested by CCU in a UL frame */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_trau_frame_dl_ta_us(const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t c6_11, c6_8, fc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* timing alignment is only communicated from CCU to TRAU in UL */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (fr->dir == OSMO_TRAU_DIR_DL)</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%);">+   switch (fr->type) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case OSMO_TRAU16_FT_FR:</span><br><span style="color: hsl(120, 100%, 40%);">+       case OSMO_TRAU16_FT_EFR:</span><br><span style="color: hsl(120, 100%, 40%);">+      case OSMO_TRAU16_FT_HR:</span><br><span style="color: hsl(120, 100%, 40%);">+       case OSMO_TRAU16_FT_AMR:</span><br><span style="color: hsl(120, 100%, 40%);">+              c6_11 = (fr->c_bits[5] << 5) | (fr->c_bits[6] << 4) | (fr->c_bits[7] << 3) |</span><br><span style="color: hsl(120, 100%, 40%);">+                       (fr->c_bits[8] << 2) | (fr->c_bits[9] << 1) | (fr->c_bits[10] << 0);</span><br><span style="color: hsl(120, 100%, 40%);">+               return trau_frame_16_ta_us(c6_11);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case OSMO_TRAU8_SPEECH:</span><br><span style="color: hsl(120, 100%, 40%);">+               c6_8 = (fr->c_bits[5] << 2) | (fr->c_bits[6] << 1) | (fr->c_bits[7] << 0);</span><br><span style="color: hsl(120, 100%, 40%);">+         return trau_frame_8_ta_us(c6_8);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case OSMO_TRAU8_AMR_LOW:</span><br><span style="color: hsl(120, 100%, 40%);">+              fc = (fr->c_bits[3] << 1) | (fr->c_bits[4] << 0);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (fc == TS48060_AMR_FC_NO_SPEECH) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 c6_11 = (fr->c_bits[5] << 5) | (fr->c_bits[6] << 4) | (fr->c_bits[7] << 3) |</span><br><span style="color: hsl(120, 100%, 40%);">+                               (fr->c_bits[8] << 2) | (fr->c_bits[9] << 1) | (fr->c_bits[10] << 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                       /* For AMR speech on 8 kBit/s submultiplexing the same procedures as for AMR</span><br><span style="color: hsl(120, 100%, 40%);">+                   * speech on 16 kBit/s submultiplexing shall be applied, see 3GPP TS 48.060 */</span><br><span style="color: hsl(120, 100%, 40%);">+                        return trau_frame_16_ta_us(c6_11);</span><br><span style="color: hsl(120, 100%, 40%);">+            } else</span><br><span style="color: hsl(120, 100%, 40%);">+                        return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      default:</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int encode16_handle_ta(ubit_t *trau_bits, const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fr->dir == OSMO_TRAU_DIR_DL) {</span><br><span style="color: hsl(120, 100%, 40%);">+         int num_bits = fr->dl_ta_usec * T16_250us / 250;</span><br><span style="color: hsl(120, 100%, 40%);">+           if (num_bits > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        if (num_bits > 39 * 8)</span><br><span style="color: hsl(120, 100%, 40%);">+                             num_bits = 39;</span><br><span style="color: hsl(120, 100%, 40%);">+                        memset(trau_bits + 40 * 8, 1, num_bits);</span><br><span style="color: hsl(120, 100%, 40%);">+                      return 40 * 8 + num_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+             } else if (num_bits < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (num_bits < -1 * T16_250us)</span><br><span style="color: hsl(120, 100%, 40%);">+                             num_bits = -1 * T16_250us;</span><br><span style="color: hsl(120, 100%, 40%);">+                    return 40 * 8 + num_bits;</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 40 * 8;</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%);">+static int encode8_handle_ta(ubit_t *trau_bits, const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     if (fr->dir == OSMO_TRAU_DIR_DL) {</span><br><span style="color: hsl(120, 100%, 40%);">+         int num_bits = fr->dl_ta_usec * T8_250us / 250;</span><br><span style="color: hsl(120, 100%, 40%);">+            if (num_bits > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        if (num_bits > 20 * 8 - 2)</span><br><span style="color: hsl(120, 100%, 40%);">+                         num_bits = 20 * 8 - 2;</span><br><span style="color: hsl(120, 100%, 40%);">+                        memset(trau_bits + 20 * 8, 1, num_bits);</span><br><span style="color: hsl(120, 100%, 40%);">+                      return 20 * 8 + num_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+             } else if (num_bits < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (num_bits < -1 * T8_250us)</span><br><span style="color: hsl(120, 100%, 40%);">+                              num_bits = -2;</span><br><span style="color: hsl(120, 100%, 40%);">+                        return 20 * 8 + num_bits;</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 20 * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* TS 08.60 Section 3.1.1 */</span><br><span> static int encode16_fr(ubit_t *trau_bits, const struct osmo_trau_frame *fr)</span><br><span> {</span><br><span>@@ -172,16 +286,7 @@</span><br><span>       memcpy(trau_bits + 316, fr->t_bits+0, 4);</span><br><span> </span><br><span>     /* handle timing adjustment */</span><br><span style="color: hsl(0, 100%, 40%);">-  if (fr->dir == OSMO_TRAU_DIR_DL) {</span><br><span style="color: hsl(0, 100%, 40%);">-           uint8_t cbits6_11 = get_bits(fr->c_bits, 5, 6);</span><br><span style="color: hsl(0, 100%, 40%);">-              int ta_bits = fr_efr_alignment_bitcount(cbits6_11);</span><br><span style="color: hsl(0, 100%, 40%);">-             if (ta_bits > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   memset(trau_bits+320, 1, ta_bits);</span><br><span style="color: hsl(0, 100%, 40%);">-                      return 320 + ta_bits;</span><br><span style="color: hsl(0, 100%, 40%);">-           } else if (ta_bits < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-                      return 320 - ta_bits;</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span style="color: hsl(0, 100%, 40%);">-       return 40 * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+        return encode16_handle_ta(trau_bits, fr);</span><br><span> }</span><br><span> </span><br><span> /* TS 08.60 Section 3.1.1 */</span><br><span>@@ -236,18 +341,9 @@</span><br><span>    /* T1 .. T4 */</span><br><span>       memcpy(trau_bits + 316, fr->t_bits + 0, 4);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      /* handle timing adjustment */</span><br><span style="color: hsl(0, 100%, 40%);">-  if (fr->dir == OSMO_TRAU_DIR_DL) {</span><br><span style="color: hsl(0, 100%, 40%);">-           uint8_t cbits6_11 = get_bits(fr->c_bits, 5, 6);</span><br><span style="color: hsl(0, 100%, 40%);">-              int ta_bits = fr_efr_alignment_bitcount(cbits6_11);</span><br><span style="color: hsl(0, 100%, 40%);">-             if (ta_bits > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   memset(trau_bits+320, 1, ta_bits);</span><br><span style="color: hsl(0, 100%, 40%);">-                      return 320 + ta_bits;</span><br><span style="color: hsl(0, 100%, 40%);">-           } else if (ta_bits < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-                      return 320 - ta_bits;</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span style="color: hsl(120, 100%, 40%);">+     return encode16_handle_ta(trau_bits, fr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  /* FIXME: handle TAE (Timing Alignment Extension) */</span><br><span style="color: hsl(0, 100%, 40%);">-    return 40 * 8;</span><br><span> }</span><br><span> </span><br><span> /* TS 08.60 Section 3.1.2 */</span><br><span>@@ -378,16 +474,7 @@</span><br><span>       memcpy(trau_bits + 39 * 8 + 4, fr->t_bits, 4);</span><br><span> </span><br><span>        /* handle timing adjustment */</span><br><span style="color: hsl(0, 100%, 40%);">-  if (fr->dir == OSMO_TRAU_DIR_DL) {</span><br><span style="color: hsl(0, 100%, 40%);">-           uint8_t cbits6_11 = get_bits(fr->c_bits, 5, 6);</span><br><span style="color: hsl(0, 100%, 40%);">-              int ta_bits = fr_efr_alignment_bitcount(cbits6_11);</span><br><span style="color: hsl(0, 100%, 40%);">-             if (ta_bits > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   memset(trau_bits+320, 1, ta_bits);</span><br><span style="color: hsl(0, 100%, 40%);">-                      return 320 + ta_bits;</span><br><span style="color: hsl(0, 100%, 40%);">-           } else if (ta_bits < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-                      return 320 - ta_bits;</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span style="color: hsl(0, 100%, 40%);">-       return 40 * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+        return encode16_handle_ta(trau_bits, fr);</span><br><span> }</span><br><span> </span><br><span> /* TS 08.61 Section 5.1.1.1 */</span><br><span>@@ -797,12 +884,12 @@</span><br><span>         /* C6 .. C9 */</span><br><span>       memcpy(trau_bits + 19 * 8 + 2, fr->c_bits + 5, 4);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       /* FIXME: handle timing adjustment */</span><br><span>        /* T1 .. T2 */</span><br><span>       trau_bits[19 * 8 + 6] = fr->t_bits[0];</span><br><span>    trau_bits[19 * 8 + 7] = fr->t_bits[1];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   return 20 * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* handle timing adjustment */</span><br><span style="color: hsl(120, 100%, 40%);">+        return encode8_handle_ta(trau_bits, fr);</span><br><span> }</span><br><span> </span><br><span> /* TS 08.61 Section 5.2.1.2.1 */</span><br><span>@@ -876,7 +963,7 @@</span><br><span>  /* T1 */</span><br><span>     trau_bits[19 * 8 + 7] = fr->t_bits[0];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   return 20 * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+        return encode8_handle_ta(trau_bits, fr);</span><br><span> }</span><br><span> </span><br><span> /* TS 08.61 Section 5.2.1.2.2 */</span><br><span>@@ -947,7 +1034,7 @@</span><br><span>                 d_idx += 15;</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   return 20 * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+        return encode8_handle_ta(trau_bits, fr);</span><br><span> }</span><br><span> </span><br><span> /* TS 08.61 Section 5.1.2.3 */</span><br><span>@@ -1006,7 +1093,7 @@</span><br><span>  /* D24 .. D151 */</span><br><span>    memcpy(trau_bits + 4 * 8, fr->d_bits + d_idx, 16 * 8);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   return 20 * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+        return encode8_handle_ta(trau_bits, fr);</span><br><span> }</span><br><span> </span><br><span> /* TS 08.61 Section 5.2.2 */</span><br><span>@@ -1185,6 +1272,7 @@</span><br><span> </span><br><span>        fr->type = OSMO_TRAU_FT_NONE;</span><br><span>     fr->dir = dir;</span><br><span style="color: hsl(120, 100%, 40%);">+     fr->dl_ta_usec = 0;</span><br><span> </span><br><span>   switch (cbits5) {</span><br><span>    case TRAU_FT_FR_UP:</span><br><span>@@ -1326,6 +1414,7 @@</span><br><span> {</span><br><span>     fr->type = OSMO_TRAU_FT_NONE;</span><br><span>     fr->dir = dir;</span><br><span style="color: hsl(120, 100%, 40%);">+     fr->dl_ta_usec = 0;</span><br><span> </span><br><span>   if (is_hr(bits)) {</span><br><span>           /* normal sync pattern */</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmo-abis/+/19504">change 19504</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/libosmo-abis/+/19504"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmo-abis </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I3981becafc56c9a50119b9ba6bf67aa0391cc76e </div>
<div style="display:none"> Gerrit-Change-Number: 19504 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>