<p>Vadim Yanitskiy has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/13732">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">trxcon: introduce extended (11-bit) RACH support<br><br>According to 3GPP TS 05.03, section 5.3, two coding schemes are<br>specified for access bursts: one for regular 8-bit bursts, another<br>for extended 11-bit packet access bursts.<br><br>Change-Id: I36fd20cd5502ce33c52f644ee4c22abb83350df8<br>---<br>M src/host/trxcon/l1ctl.c<br>M src/host/trxcon/sched_lchan_rach.c<br>2 files changed, 125 insertions(+), 49 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/32/13732/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/host/trxcon/l1ctl.c b/src/host/trxcon/l1ctl.c</span><br><span>index 97c2496..653ddf3 100644</span><br><span>--- a/src/host/trxcon/l1ctl.c</span><br><span>+++ b/src/host/trxcon/l1ctl.c</span><br><span>@@ -500,8 +500,9 @@</span><br><span>         return rc;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int l1ctl_rx_rach_req(struct l1ctl_link *l1l, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+static int l1ctl_rx_rach_req(struct l1ctl_link *l1l, struct msgb *msg, bool ext)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+      struct l1ctl_ext_rach_req *ext_req;</span><br><span>  struct l1ctl_rach_req *req;</span><br><span>  struct l1ctl_info_ul *ul;</span><br><span>    struct trx_ts_prim *prim;</span><br><span>@@ -510,11 +511,25 @@</span><br><span>    int rc;</span><br><span> </span><br><span>  ul = (struct l1ctl_info_ul *) msg->l1h;</span><br><span style="color: hsl(0, 100%, 40%);">-      req = (struct l1ctl_rach_req *) ul->payload;</span><br><span style="color: hsl(0, 100%, 40%);">- len = sizeof(struct l1ctl_rach_req);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        /* Convert offset value to host format */</span><br><span style="color: hsl(0, 100%, 40%);">-       req->offset = ntohs(req->offset);</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Is it extended (11-bit) RACH or not? */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (ext) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ext_req = (struct l1ctl_ext_rach_req *) ul->payload;</span><br><span style="color: hsl(120, 100%, 40%);">+               ext_req->offset = ntohs(ext_req->offset);</span><br><span style="color: hsl(120, 100%, 40%);">+               ext_req->ra11 = ntohs(ext_req->ra11);</span><br><span style="color: hsl(120, 100%, 40%);">+           len = sizeof(*ext_req);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             LOGP(DL1C, LOGL_NOTICE, "Received extended (11-bit) RACH request "</span><br><span style="color: hsl(120, 100%, 40%);">+                  "(offset=%u, synch_seq=%u, ra11=0x%02hx)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                        ext_req->offset, ext_req->synch_seq, ext_req->ra11);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              req = (struct l1ctl_rach_req *) ul->payload;</span><br><span style="color: hsl(120, 100%, 40%);">+               req->offset = ntohs(req->offset);</span><br><span style="color: hsl(120, 100%, 40%);">+               len = sizeof(*req);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         LOGP(DL1C, LOGL_NOTICE, "Received regular (8-bit) RACH request "</span><br><span style="color: hsl(120, 100%, 40%);">+                    "(offset=%u, ra=0x%02x)\n", req->offset, req->ra);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span> </span><br><span>        /**</span><br><span>   * FIXME: l1ctl_info_ul doesn't provide channel description</span><br><span>@@ -523,9 +538,6 @@</span><br><span>        chan_nr = 0x88;</span><br><span>      link_id = 0x00;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     LOGP(DL1C, LOGL_NOTICE, "Received RACH request "</span><br><span style="color: hsl(0, 100%, 40%);">-              "(offset=%u ra=0x%02x)\n", req->offset, req->ra);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>    /* Init a new primitive */</span><br><span>   rc = sched_prim_init(l1l->trx, &prim, len, chan_nr, link_id);</span><br><span>         if (rc)</span><br><span>@@ -544,7 +556,7 @@</span><br><span>        }</span><br><span> </span><br><span>        /* Fill in the payload */</span><br><span style="color: hsl(0, 100%, 40%);">-       memcpy(prim->payload, req, len);</span><br><span style="color: hsl(120, 100%, 40%);">+   memcpy(prim->payload, ul->payload, len);</span><br><span> </span><br><span> exit:</span><br><span>  msgb_free(msg);</span><br><span>@@ -845,7 +857,9 @@</span><br><span>        case L1CTL_CCCH_MODE_REQ:</span><br><span>            return l1ctl_rx_ccch_mode_req(l1l, msg);</span><br><span>     case L1CTL_RACH_REQ:</span><br><span style="color: hsl(0, 100%, 40%);">-            return l1ctl_rx_rach_req(l1l, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+           return l1ctl_rx_rach_req(l1l, msg, false);</span><br><span style="color: hsl(120, 100%, 40%);">+    case L1CTL_EXT_RACH_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+              return l1ctl_rx_rach_req(l1l, msg, true);</span><br><span>    case L1CTL_DM_EST_REQ:</span><br><span>               return l1ctl_rx_dm_est_req(l1l, msg);</span><br><span>        case L1CTL_DM_REL_REQ:</span><br><span>diff --git a/src/host/trxcon/sched_lchan_rach.c b/src/host/trxcon/sched_lchan_rach.c</span><br><span>index ecf5df8..b2e5f9f 100644</span><br><span>--- a/src/host/trxcon/sched_lchan_rach.c</span><br><span>+++ b/src/host/trxcon/sched_lchan_rach.c</span><br><span>@@ -40,68 +40,130 @@</span><br><span> #include "trx_if.h"</span><br><span> #include "l1ctl.h"</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/**</span><br><span style="color: hsl(0, 100%, 40%);">- * 8-bit RACH extended tail bits</span><br><span style="color: hsl(0, 100%, 40%);">- * GSM 05.02 Chapter 5.2.7 Access burst (AB)</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(120, 100%, 40%);">+/* FIXME: we need a better way to identify / distinguish primitives */</span><br><span style="color: hsl(120, 100%, 40%);">+#define PRIM_IS_EXT_RACH(prim) \</span><br><span style="color: hsl(120, 100%, 40%);">+   (prim->payload_len == sizeof(struct l1ctl_ext_rach_req))</span><br><span style="color: hsl(120, 100%, 40%);">+#define PRIM_IS_RACH(prim) \</span><br><span style="color: hsl(120, 100%, 40%);">+     (prim->payload_len == sizeof(struct l1ctl_rach_req))</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static ubit_t rach_ext_tail_bits[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+/* 3GPP TS 05.02, section 5.2.7 "Access burst (AB)" */</span><br><span style="color: hsl(120, 100%, 40%);">+#define RACH_EXT_TAIL_BITS_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%);">+#define RACH_PAYLOAD_LEN    36</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Extended tail bits (BN0..BN7) */</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t rach_ext_tail_bits[] = {</span><br><span>      0, 0, 1, 1, 1, 0, 1, 0,</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/**</span><br><span style="color: hsl(0, 100%, 40%);">- * 41-bit RACH synchronization sequence</span><br><span style="color: hsl(0, 100%, 40%);">- * GSM 05.02 Chapter 5.2.7 Access burst (AB)</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static ubit_t rach_synch_seq[] = {</span><br><span style="color: hsl(0, 100%, 40%);">-    0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,</span><br><span style="color: hsl(0, 100%, 40%);">-       1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0,</span><br><span style="color: hsl(0, 100%, 40%);">-       1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+/* Synchronization (training) sequence types */</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%);">+/* Synchronization (training) sequence bits */</span><br><span style="color: hsl(120, 100%, 40%);">+static const char rach_synch_seq_bits[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%);">+/* Synchronization (training) sequence names */</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> };</span><br><span> </span><br><span> /* Obtain a to-be-transmitted RACH burst */</span><br><span> int tx_rach_fn(struct trx_instance *trx, struct trx_ts *ts,</span><br><span>         struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-   struct l1ctl_rach_req *req;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct l1ctl_ext_rach_req *ext_req = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct l1ctl_rach_req *req = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+    enum rach_synch_seq_t synch_seq;</span><br><span>     uint8_t burst[GSM_BURST_LEN];</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *burst_ptr = burst;</span><br><span>  uint8_t payload[36];</span><br><span style="color: hsl(0, 100%, 40%);">-    int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       int i, rc;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  /* Check the prim payload length */</span><br><span style="color: hsl(0, 100%, 40%);">-     if (lchan->prim->payload_len != sizeof(*req)) {</span><br><span style="color: hsl(0, 100%, 40%);">-           LOGP(DSCHD, LOGL_ERROR, "Primitive has odd length %zu (expected %zu), "</span><br><span style="color: hsl(0, 100%, 40%);">-                       "so dropping...\n", lchan->prim->payload_len, sizeof(*req));</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Is it extended (11-bit) RACH or not? */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (PRIM_IS_EXT_RACH(lchan->prim)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ext_req = (struct l1ctl_ext_rach_req *) lchan->prim->payload;</span><br><span style="color: hsl(120, 100%, 40%);">+           synch_seq = ext_req->synch_seq;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+                /* Delay sending according to offset value */</span><br><span style="color: hsl(120, 100%, 40%);">+         if (ext_req->offset-- > 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%);">+           /* Chose a synch. sequence */</span><br><span style="color: hsl(120, 100%, 40%);">+         if (synch_seq >= RACH_SYNCH_SEQ_NUM) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     LOGP(DSCHD, LOGL_ERROR, "Unknown RACH synch. sequence=0x%02x\n", synch_seq);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* Forget this primitive */</span><br><span style="color: hsl(120, 100%, 40%);">+                   sched_prim_drop(lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+                       return -ENOTSUP;</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%);">+           /* Encode extended (11-bit) payload */</span><br><span style="color: hsl(120, 100%, 40%);">+                rc = gsm0503_rach_ext_encode(payload, ext_req->ra11, trx->bsic, true);</span><br><span style="color: hsl(120, 100%, 40%);">+          if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     LOGP(DSCHD, LOGL_ERROR, "Could not encode extended RACH burst\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                        /* Forget this primitive */</span><br><span style="color: hsl(120, 100%, 40%);">+                   sched_prim_drop(lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+                       return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else if (PRIM_IS_RACH(lchan->prim)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            req = (struct l1ctl_rach_req *) lchan->prim->payload;</span><br><span style="color: hsl(120, 100%, 40%);">+           synch_seq = RACH_SYNCH_SEQ_TS0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Delay sending according to offset value */</span><br><span style="color: hsl(120, 100%, 40%);">+         if (req->offset-- > 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%);">+           /* Encode regular (8-bit) payload */</span><br><span style="color: hsl(120, 100%, 40%);">+          rc = gsm0503_rach_ext_encode(payload, req->ra, trx->bsic, false);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     LOGP(DSCHD, LOGL_ERROR, "Could not encode RACH burst\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                 /* Forget this primitive */</span><br><span style="color: hsl(120, 100%, 40%);">+                   sched_prim_drop(lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+                       return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGP(DSCHD, LOGL_ERROR, "Primitive has odd length %zu (expected %zu or %zu), "</span><br><span style="color: hsl(120, 100%, 40%);">+                      "so dropping...\n", lchan->prim->payload_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                 sizeof(*req), sizeof(*ext_req));</span><br><span>             sched_prim_drop(lchan);</span><br><span>              return -EINVAL;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* Get the payload from a current primitive */</span><br><span style="color: hsl(0, 100%, 40%);">-  req = (struct l1ctl_rach_req *) lchan->prim->payload;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* Delay RACH sending according to offset value */</span><br><span style="color: hsl(0, 100%, 40%);">-      if (req->offset-- > 0)</span><br><span style="color: hsl(0, 100%, 40%);">-            return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     /* BN0-7: extended tail bits */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(burst_ptr, rach_ext_tail_bits, RACH_EXT_TAIL_BITS_LEN);</span><br><span style="color: hsl(120, 100%, 40%);">+        burst_ptr += RACH_EXT_TAIL_BITS_LEN;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        /* Encode (8-bit) payload */</span><br><span style="color: hsl(0, 100%, 40%);">-    rc = gsm0503_rach_ext_encode(payload, req->ra, trx->bsic, false);</span><br><span style="color: hsl(0, 100%, 40%);">- if (rc) {</span><br><span style="color: hsl(0, 100%, 40%);">-               LOGP(DSCHD, LOGL_ERROR, "Could not encode RACH burst\n");</span><br><span style="color: hsl(120, 100%, 40%);">+   /* BN8-48: chosen synch. (training) sequence */</span><br><span style="color: hsl(120, 100%, 40%);">+       for (i = 0; i < RACH_SYNCH_SEQ_LEN; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+           *(burst_ptr++) = rach_synch_seq_bits[synch_seq][i] == '1';</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-          /* Forget this primitive */</span><br><span style="color: hsl(0, 100%, 40%);">-             sched_prim_drop(lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+       /* BN49-84: encrypted bits (the payload) */</span><br><span style="color: hsl(120, 100%, 40%);">+   memcpy(burst_ptr, payload, RACH_PAYLOAD_LEN);</span><br><span style="color: hsl(120, 100%, 40%);">+ burst_ptr += RACH_PAYLOAD_LEN;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-              return rc;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* BN85-156: tail bits & extended guard period */</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(burst_ptr, 0, burst + GSM_BURST_LEN - burst_ptr);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    /* Compose RACH burst */</span><br><span style="color: hsl(0, 100%, 40%);">-        memcpy(burst, rach_ext_tail_bits, 8); /* TB */</span><br><span style="color: hsl(0, 100%, 40%);">-  memcpy(burst + 8, rach_synch_seq, 41); /* sync seq */</span><br><span style="color: hsl(0, 100%, 40%);">-   memcpy(burst + 49, payload, 36); /* payload */</span><br><span style="color: hsl(0, 100%, 40%);">-  memset(burst + 85, 0, 63); /* TB + GP */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        LOGP(DSCHD, LOGL_DEBUG, "Transmitting RACH fn=%u\n", fn);</span><br><span style="color: hsl(120, 100%, 40%);">+   LOGP(DSCHD, LOGL_DEBUG, "Transmitting %s RACH (%s) fn=%u\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                PRIM_IS_EXT_RACH(lchan->prim) ? "extended (11-bit)" : "regular (8-bit)",</span><br><span style="color: hsl(120, 100%, 40%);">+               get_value_string(rach_synch_seq_names, synch_seq), fn);</span><br><span> </span><br><span>  /* Forward burst to scheduler */</span><br><span>     rc = sched_trx_handle_tx_burst(trx, ts, lchan, fn, burst);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/13732">change 13732</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/13732"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmocom-bb </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I36fd20cd5502ce33c52f644ee4c22abb83350df8 </div>
<div style="display:none"> Gerrit-Change-Number: 13732 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Vadim Yanitskiy <axilirator@gmail.com> </div>