<p>Alexander Chemeris <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/13723">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Vadim Yanitskiy: Looks good to me, approved; Verified
  Jenkins Builder: Verified

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">osmo-bts-trx: distinguish 11-bit Access Bursts by synch. sequence<br><br>Thanks to both TC_rach_content and TC_rach_count TTCN-3 test cases,<br>it was discovered that there are possible collisions when trying<br>to decode a regular 8-bit Access Burst as an 11-bit one. This is<br>exactly what we are doing in rx_rach_fn():<br><br>  - calling gsm0503_rach_ext_decode_ber() first,<br>  - if it failed, falling-back to gsm0503_rach_decode_ber().<br><br>With default BSIC=63, the following 8-bit RA values are being<br>misinterpreted as 11-bit Access Bursts:<br><br>  Successfully decoded 8-bit (0x00) RACH as 11-bit (0x0000): bsic=0x3f<br>  Successfully decoded 8-bit (0xbe) RACH as 11-bit (0x0388): bsic=0x3f<br>  Successfully decoded 8-bit (0xcf) RACH as 11-bit (0x0036): bsic=0x3f<br><br>According to 3GPP TS 05.02, section 5.2.7, there are two alternative<br>synch. (training) sequences for Access Bursts: TS1 & TS2. By default,<br>TS0 synch. sequence is used, unless explicitly stated otherwise<br>(see 3GPP TS 04.60).<br><br>According to 3GPP TS 04.60, section 11.2.5a, the EGPRS capability<br>can be indicated by the MS using one of the alternative training<br>sequences (i.e. TS1 or TS2) and the 11-bit RACH coding scheme.<br><br>In other words, knowing the synch. sequence of a received Access<br>Burst would allow to decide whether it's extended (11-bit)<br>or a regular (8-bit) one. As a result, we would avoid possible<br>collisions and save some CPU power.<br><br>Unfortunately, due to the limitations of the current TRXD protocol,<br>there is no easy way to expose such information from the transceiver.<br>A proper solution would be to extend the TRX protocol, but for now,<br>let's do the synch. sequence detection in rx_rach_fn(). As soon as<br>the TRX protocol is extended with info about the synch. sequence,<br>this code would serve for the backwards-compatibility.<br><br>This change makes the both TC_rach_content and TC_rach_count happy,<br>as well as the new TC_pcu_ext_rach_content() test case aimed to<br>verify extended (11-bit) Access Burst decoding.<br><br>Related (TTCN-3) I8fe156aeac9de3dc1e71a4950821d4942ba9a253<br>Change-Id: Ibb6d27c6589965c8b59a6d2598a7c43fd860f284<br>Related: OS#1854<br>---<br>M src/osmo-bts-trx/scheduler_trx.c<br>1 file changed, 123 insertions(+), 42 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c</span><br><span>index 32bdb98..ade3cff 100644</span><br><span>--- a/src/osmo-bts-trx/scheduler_trx.c</span><br><span>+++ b/src/osmo-bts-trx/scheduler_trx.c</span><br><span>@@ -22,6 +22,7 @@</span><br><span>  */</span><br><span> #include <stdlib.h></span><br><span> #include <unistd.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <limits.h></span><br><span> #include <errno.h></span><br><span> #include <stdint.h></span><br><span> #include <ctype.h></span><br><span>@@ -709,72 +710,152 @@</span><br><span>  * RX on uplink (indication to upper layer)</span><br><span>  */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* 3GPP TS 05.02, section 5.2.7 */</span><br><span style="color: hsl(120, 100%, 40%);">+#define RACH_EXT_TAIL_LEN 8</span><br><span style="color: hsl(120, 100%, 40%);">+#define RACH_SYNCH_SEQ_LEN   41</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum rach_synch_seq_t {</span><br><span style="color: hsl(120, 100%, 40%);">+ RACH_SYNCH_SEQ_UNKNOWN = -1,</span><br><span style="color: hsl(120, 100%, 40%);">+  RACH_SYNCH_SEQ_TS0, /* GSM, GMSK (default) */</span><br><span style="color: hsl(120, 100%, 40%);">+ RACH_SYNCH_SEQ_TS1, /* EGPRS, 8-PSK */</span><br><span style="color: hsl(120, 100%, 40%);">+        RACH_SYNCH_SEQ_TS2, /* EGPRS, GMSK */</span><br><span style="color: hsl(120, 100%, 40%);">+ RACH_SYNCH_SEQ_NUM</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 struct value_string rach_synch_seq_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+       { RACH_SYNCH_SEQ_UNKNOWN,       "UNKNOWN" },</span><br><span style="color: hsl(120, 100%, 40%);">+        { RACH_SYNCH_SEQ_TS0,           "TS0: GSM, GMSK" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { RACH_SYNCH_SEQ_TS1,           "TS1: EGPRS, 8-PSK" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { RACH_SYNCH_SEQ_TS2,           "TS2: EGPRS, GMSK" },</span><br><span style="color: hsl(120, 100%, 40%);">+       { 0, NULL },</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 enum rach_synch_seq_t rach_get_synch_seq(sbit_t *bits, int *best_score)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ sbit_t *synch_seq_burst = bits + RACH_EXT_TAIL_LEN;</span><br><span style="color: hsl(120, 100%, 40%);">+   enum rach_synch_seq_t seq = RACH_SYNCH_SEQ_TS0;</span><br><span style="color: hsl(120, 100%, 40%);">+       int score[RACH_SYNCH_SEQ_NUM] = { 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+        int max_score = INT_MIN;</span><br><span style="color: hsl(120, 100%, 40%);">+      int i, j;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* 3GPP TS 05.02, section 5.2.7 "Access burst (AB)", synch. sequence bits */</span><br><span style="color: hsl(120, 100%, 40%);">+        static const char synch_seq_ref[RACH_SYNCH_SEQ_NUM][RACH_SYNCH_SEQ_LEN] = {</span><br><span style="color: hsl(120, 100%, 40%);">+           [RACH_SYNCH_SEQ_TS0] = "01001011011111111001100110101010001111000",</span><br><span style="color: hsl(120, 100%, 40%);">+         [RACH_SYNCH_SEQ_TS1] = "01010100111110001000011000101111001001101",</span><br><span style="color: hsl(120, 100%, 40%);">+         [RACH_SYNCH_SEQ_TS2] = "11101111001001110101011000001101101110111",</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%);">+  /* Get a multiplier for j-th bit of i-th synch. sequence */</span><br><span style="color: hsl(120, 100%, 40%);">+#define RACH_SYNCH_SEQ_MULT \</span><br><span style="color: hsl(120, 100%, 40%);">+    (synch_seq_ref[i][j] == '1' ? -1 : 1)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* For each synch. sequence, count the bit match score. Since we deal with</span><br><span style="color: hsl(120, 100%, 40%);">+     * soft-bits (-127...127), we sum the absolute values of matching ones,</span><br><span style="color: hsl(120, 100%, 40%);">+        * and subtract the absolute values of different ones, so the resulting</span><br><span style="color: hsl(120, 100%, 40%);">+        * score is more accurate than it could be with hard-bits. */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < RACH_SYNCH_SEQ_NUM; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         for (j = 0; j < RACH_SYNCH_SEQ_LEN; j++)</span><br><span style="color: hsl(120, 100%, 40%);">+                   score[i] += RACH_SYNCH_SEQ_MULT * synch_seq_burst[j];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               /* Keep the maximum value updated */</span><br><span style="color: hsl(120, 100%, 40%);">+          if (score[i] > max_score) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        max_score = score[i];</span><br><span style="color: hsl(120, 100%, 40%);">+                 seq = 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Calculate an approximate level of our confidence */</span><br><span style="color: hsl(120, 100%, 40%);">+        if (best_score != NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+               *best_score = max_score;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* At least 1/3 of a synch. sequence shall match */</span><br><span style="color: hsl(120, 100%, 40%);">+   if (max_score < (127 * RACH_SYNCH_SEQ_LEN / 3))</span><br><span style="color: hsl(120, 100%, 40%);">+            return RACH_SYNCH_SEQ_UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return seq;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int rx_rach_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,</span><br><span>         enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,</span><br><span>  int8_t rssi, int16_t toa256)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-       uint8_t chan_nr;</span><br><span>     struct osmo_phsap_prim l1sap;</span><br><span>        int n_errors, n_bits_total;</span><br><span style="color: hsl(0, 100%, 40%);">-     bool is_11bit = true;</span><br><span>        uint16_t ra11;</span><br><span>       uint8_t ra;</span><br><span style="color: hsl(0, 100%, 40%);">-     int rc = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+   int rc;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     chan_nr = trx_chan_desc[chan].chan_nr | tn;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* It would be great if the transceiver were doing some kind of tagging,</span><br><span style="color: hsl(120, 100%, 40%);">+       * whether it is extended (11-bit) RACH or not. We would not need to guess</span><br><span style="color: hsl(120, 100%, 40%);">+     * it here. For now, let's try to correlate the synch. sequence of a received</span><br><span style="color: hsl(120, 100%, 40%);">+      * Access Burst with the known ones (3GPP TS 05.02, section 5.2.7), and</span><br><span style="color: hsl(120, 100%, 40%);">+        * fall-back to the default TS0 if it fails. This would save some CPU</span><br><span style="color: hsl(120, 100%, 40%);">+  * power, and what is more important - prevent possible collisions. */</span><br><span style="color: hsl(120, 100%, 40%);">+        enum rach_synch_seq_t synch_seq = RACH_SYNCH_SEQ_TS0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int best_score = 127 * RACH_SYNCH_SEQ_LEN;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received RACH toa=%d\n", toa256);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Handover RACH cannot be extended (11-bit) */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (chan == TRXC_RACH)</span><br><span style="color: hsl(120, 100%, 40%);">+                synch_seq = rach_get_synch_seq(bits, &best_score);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      if (chan == TRXC_RACH) /* Attempt to decode as extended (11-bit) RACH first */</span><br><span style="color: hsl(0, 100%, 40%);">-          rc = gsm0503_rach_ext_decode_ber(&ra11, bits + 8 + 41,</span><br><span style="color: hsl(120, 100%, 40%);">+    LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn,</span><br><span style="color: hsl(120, 100%, 40%);">+          "Received RACH (%s; match=%.1f%%) toa=%d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+        get_value_string(rach_synch_seq_names, synch_seq),</span><br><span style="color: hsl(120, 100%, 40%);">+            best_score * 100.0 / (127 * RACH_SYNCH_SEQ_LEN),</span><br><span style="color: hsl(120, 100%, 40%);">+              toa256);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Compose a new L1SAP primitive */</span><br><span style="color: hsl(120, 100%, 40%);">+   memset(&l1sap, 0x00, sizeof(l1sap));</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_PH_RACH, PRIM_OP_INDICATION, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+   l1sap.u.rach_ind.chan_nr = trx_chan_desc[chan].chan_nr | tn;</span><br><span style="color: hsl(120, 100%, 40%);">+  l1sap.u.rach_ind.acc_delay = (toa256 >= 0) ? toa256 / 256 : 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     l1sap.u.rach_ind.acc_delay_256bits = toa256;</span><br><span style="color: hsl(120, 100%, 40%);">+  l1sap.u.rach_ind.rssi = rssi;</span><br><span style="color: hsl(120, 100%, 40%);">+ l1sap.u.rach_ind.fn = fn;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Decode RACH depending on its synch. sequence */</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (synch_seq) {</span><br><span style="color: hsl(120, 100%, 40%);">+  case RACH_SYNCH_SEQ_TS1:</span><br><span style="color: hsl(120, 100%, 40%);">+      case RACH_SYNCH_SEQ_TS2:</span><br><span style="color: hsl(120, 100%, 40%);">+              rc = gsm0503_rach_ext_decode_ber(&ra11, bits + RACH_EXT_TAIL_LEN + RACH_SYNCH_SEQ_LEN,</span><br><span>                                            l1t->trx->bts->bsic, &n_errors, &n_bits_total);</span><br><span style="color: hsl(0, 100%, 40%);">-       if (rc) {</span><br><span style="color: hsl(0, 100%, 40%);">-               /* Indicate non-extended RACH */</span><br><span style="color: hsl(0, 100%, 40%);">-                is_11bit = false;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               /* Fall-back to the normal RACH decoding */</span><br><span style="color: hsl(0, 100%, 40%);">-             rc = gsm0503_rach_decode_ber(&ra, bits + 8 + 41,</span><br><span style="color: hsl(0, 100%, 40%);">-                    l1t->trx->bts->bsic, &n_errors, &n_bits_total);</span><br><span>             if (rc) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received bad AB frame\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                     LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received bad Access Burst\n");</span><br><span>                        return 0;</span><br><span>            }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* compose primitive */</span><br><span style="color: hsl(0, 100%, 40%);">- /* generate prim */</span><br><span style="color: hsl(0, 100%, 40%);">-     memset(&l1sap, 0, sizeof(l1sap));</span><br><span style="color: hsl(0, 100%, 40%);">-   osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_PH_RACH, PRIM_OP_INDICATION,</span><br><span style="color: hsl(0, 100%, 40%);">-            NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-  l1sap.u.rach_ind.chan_nr = chan_nr;</span><br><span style="color: hsl(0, 100%, 40%);">-     l1sap.u.rach_ind.acc_delay = (toa256 >= 0) ? toa256/256 : 0;</span><br><span style="color: hsl(0, 100%, 40%);">- l1sap.u.rach_ind.fn = fn;</span><br><span style="color: hsl(0, 100%, 40%);">-       l1sap.u.rach_ind.rssi = rssi;</span><br><span style="color: hsl(0, 100%, 40%);">-   l1sap.u.rach_ind.ber10k = compute_ber10k(n_bits_total, n_errors);</span><br><span style="color: hsl(0, 100%, 40%);">-       l1sap.u.rach_ind.acc_delay_256bits = toa256;</span><br><span style="color: hsl(120, 100%, 40%);">+          if (synch_seq == RACH_SYNCH_SEQ_TS1)</span><br><span style="color: hsl(120, 100%, 40%);">+                  l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_ACCESS_1;</span><br><span style="color: hsl(120, 100%, 40%);">+             else</span><br><span style="color: hsl(120, 100%, 40%);">+                  l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_ACCESS_2;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (is_11bit) {</span><br><span>              l1sap.u.rach_ind.is_11bit = 1;</span><br><span>               l1sap.u.rach_ind.ra = ra11;</span><br><span style="color: hsl(0, 100%, 40%);">-             l1sap.u.rach_ind.burst_type = BSIC2BCC(l1t->trx->bts->bsic);</span><br><span style="color: hsl(0, 100%, 40%);">-           switch (l1sap.u.rach_ind.burst_type) {</span><br><span style="color: hsl(0, 100%, 40%);">-          case GSM_L1_BURST_TYPE_ACCESS_0:</span><br><span style="color: hsl(0, 100%, 40%);">-                case GSM_L1_BURST_TYPE_ACCESS_1:</span><br><span style="color: hsl(0, 100%, 40%);">-                case GSM_L1_BURST_TYPE_ACCESS_2:</span><br><span style="color: hsl(0, 100%, 40%);">-                        break;</span><br><span style="color: hsl(0, 100%, 40%);">-          default:</span><br><span style="color: hsl(0, 100%, 40%);">-                        LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn,</span><br><span style="color: hsl(0, 100%, 40%);">-                           "Received RACH frame with unexpected TSC %u, "</span><br><span style="color: hsl(0, 100%, 40%);">-                        "forcing default %u\n", l1sap.u.rach_ind.burst_type,</span><br><span style="color: hsl(0, 100%, 40%);">-                          GSM_L1_BURST_TYPE_ACCESS_0);</span><br><span style="color: hsl(0, 100%, 40%);">-                     l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_ACCESS_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%);">+      case RACH_SYNCH_SEQ_TS0:</span><br><span style="color: hsl(120, 100%, 40%);">+      default:</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Fall-back to the default TS0 if needed */</span><br><span style="color: hsl(120, 100%, 40%);">+          if (synch_seq != RACH_SYNCH_SEQ_TS0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Falling-back to the default TS0\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                   synch_seq = RACH_SYNCH_SEQ_TS0;</span><br><span>              }</span><br><span style="color: hsl(0, 100%, 40%);">-       } else {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            rc = gsm0503_rach_decode_ber(&ra, bits + RACH_EXT_TAIL_LEN + RACH_SYNCH_SEQ_LEN,</span><br><span style="color: hsl(120, 100%, 40%);">+                                       l1t->trx->bts->bsic, &n_errors, &n_bits_total);</span><br><span style="color: hsl(120, 100%, 40%);">+         if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received bad Access Burst\n");</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%);">+           l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_ACCESS_0;</span><br><span>            l1sap.u.rach_ind.is_11bit = 0;</span><br><span>               l1sap.u.rach_ind.ra = ra;</span><br><span style="color: hsl(0, 100%, 40%);">-               l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_ACCESS_0;</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span>       }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ l1sap.u.rach_ind.ber10k = compute_ber10k(n_bits_total, n_errors);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  /* forward primitive */</span><br><span>      l1sap_up(l1t->trx, &l1sap);</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/13723">change 13723</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/13723"/><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: Ibb6d27c6589965c8b59a6d2598a7c43fd860f284 </div>
<div style="display:none"> Gerrit-Change-Number: 13723 </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: Alexander Chemeris <Alexander.Chemeris@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>
<div style="display:none"> Gerrit-CC: Max <suraev@alumni.ntnu.no> </div>