<p>Stefan Sperling <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/11463">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add MGCP CRCX command statistics to osmo-mgw<br><br>Add a counter group for CRCX commands. The group contains counters for<br>successful connection processing as well as various error conditions.<br>This provides a quick overview of CRCX failures on each trunk throughout<br>the lifetime of the osmo-mgw process.<br><br>For example, after running the TTCN3 mgw test suite, the counters show<br>the following values:<br><br>OsmoMGW> show rate-counters<br>crxc statistics:<br>             crcx:success:         88 (0/s 88/m 0/h 0/d) CRCX command processed successfully.<br>          crcx:bad_action:          0 (0/s 0/m 0/h 0/d) bad action in CRCX command.<br>     crcx:unhandled_param:          1 (0/s 1/m 0/h 0/d) unhandled parameter in CRCX command.<br>      crcx:missing_callid:          1 (0/s 1/m 0/h 0/d) missing CallId in CRCX command.<br>        crcx:invalid_mode:          1 (0/s 1/m 0/h 0/d) connection invalid mode in CRCX command.<br>      crcx:limit_exceeded:          0 (0/s 0/m 0/h 0/d) limit of concurrent connections was reached.<br>       crcx:unkown_callid:          0 (0/s 0/m 0/h 0/d) unknown CallId in CRCX command.<br>     crcx:alloc_conn_fail:          0 (0/s 0/m 0/h 0/d) connection allocation failure.<br> crcx:no_remote_conn_desc:          1 (0/s 1/m 0/h 0/d) no opposite end specified for connection.<br>   crcx:start_rtp_failure:          0 (0/s 0/m 0/h 0/d) failure to start RTP processing.<br>       crcx:conn_rejected:          0 (0/s 0/m 0/h 0/d) connection rejected by policy.<br>OsmoMGW><br><br>These same counters are now also shown by 'show mgcp stats'<br>in the context of the trunk which they belong to.<br><br>With input from Philipp Maier.<br><br>Change-Id: Ida82fc340d5c66180e5fe9a0d195e9be6dc64c61<br>Related: OS#2660<br>---<br>M include/osmocom/mgcp/mgcp.h<br>M src/libosmo-mgcp/mgcp_protocol.c<br>M src/libosmo-mgcp/mgcp_vty.c<br>3 files changed, 86 insertions(+), 3 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/mgcp/mgcp.h b/include/osmocom/mgcp/mgcp.h</span><br><span>index bdc86fc..f9f0ac7 100644</span><br><span>--- a/include/osmocom/mgcp/mgcp.h</span><br><span>+++ b/include/osmocom/mgcp/mgcp.h</span><br><span>@@ -118,6 +118,21 @@</span><br><span> #define MGCP_KEEPALIVE_ONCE (-1)</span><br><span> #define MGCP_KEEPALIVE_NEVER 0</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* Global MCGP CRCX related rate counters */</span><br><span style="color: hsl(120, 100%, 40%);">+enum {</span><br><span style="color: hsl(120, 100%, 40%);">+    MGCP_CRCX_SUCCESS,</span><br><span style="color: hsl(120, 100%, 40%);">+    MGCP_CRCX_FAIL_BAD_ACTION,</span><br><span style="color: hsl(120, 100%, 40%);">+    MGCP_CRCX_FAIL_UNHANDLED_PARAM,</span><br><span style="color: hsl(120, 100%, 40%);">+       MGCP_CRCX_FAIL_MISSING_CALLID,</span><br><span style="color: hsl(120, 100%, 40%);">+        MGCP_CRCX_FAIL_INVALID_MODE,</span><br><span style="color: hsl(120, 100%, 40%);">+  MGCP_CRCX_FAIL_LIMIT_EXCEEDED,</span><br><span style="color: hsl(120, 100%, 40%);">+        MGCP_CRCX_FAIL_UNKNOWN_CALLID,</span><br><span style="color: hsl(120, 100%, 40%);">+        MGCP_CRCX_FAIL_ALLOC_CONN,</span><br><span style="color: hsl(120, 100%, 40%);">+    MGCP_CRCX_FAIL_NO_REMOTE_CONN_DESC,</span><br><span style="color: hsl(120, 100%, 40%);">+   MGCP_CRCX_FAIL_START_RTP,</span><br><span style="color: hsl(120, 100%, 40%);">+     MGCP_CRCX_FAIL_REJECTED_BY_POLICY,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct mgcp_trunk_config {</span><br><span>       struct llist_head entry;</span><br><span> </span><br><span>@@ -155,6 +170,9 @@</span><br><span>   unsigned int number_endpoints;</span><br><span>       int vty_number_endpoints;</span><br><span>    struct mgcp_endpoint *endpoints;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* rate counters */</span><br><span style="color: hsl(120, 100%, 40%);">+   struct rate_ctr_group *mgcp_crcx_ctr_group;</span><br><span> };</span><br><span> </span><br><span> enum mgcp_role {</span><br><span>diff --git a/src/libosmo-mgcp/mgcp_protocol.c b/src/libosmo-mgcp/mgcp_protocol.c</span><br><span>index e17bdae..bc35e5c 100644</span><br><span>--- a/src/libosmo-mgcp/mgcp_protocol.c</span><br><span>+++ b/src/libosmo-mgcp/mgcp_protocol.c</span><br><span>@@ -32,6 +32,7 @@</span><br><span> #include <osmocom/core/msgb.h></span><br><span> #include <osmocom/core/talloc.h></span><br><span> #include <osmocom/core/select.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/stats.h></span><br><span> </span><br><span> #include <osmocom/mgcp/mgcp.h></span><br><span> #include <osmocom/mgcp/mgcp_common.h></span><br><span>@@ -51,6 +52,28 @@</span><br><span> #define MGCP_REQUEST(NAME, REQ, DEBUG_NAME) \</span><br><span>       { .name = NAME, .handle_request = REQ, .debug_name = DEBUG_NAME },</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static const struct rate_ctr_desc mgcp_crcx_ctr_desc[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+    [MGCP_CRCX_SUCCESS] = {"crcx:success", "CRCX command processed successfully."},</span><br><span style="color: hsl(120, 100%, 40%);">+   [MGCP_CRCX_FAIL_BAD_ACTION] = {"crcx:bad_action", "bad action in CRCX command."},</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_UNHANDLED_PARAM] = {"crcx:unhandled_param", "unhandled parameter in CRCX command."},</span><br><span style="color: hsl(120, 100%, 40%);">+      [MGCP_CRCX_FAIL_MISSING_CALLID] = {"crcx:missing_callid", "missing CallId in CRCX command."},</span><br><span style="color: hsl(120, 100%, 40%);">+     [MGCP_CRCX_FAIL_INVALID_MODE] = {"crcx:invalid_mode", "connection invalid mode in CRCX command."},</span><br><span style="color: hsl(120, 100%, 40%);">+        [MGCP_CRCX_FAIL_LIMIT_EXCEEDED] = {"crcx:limit_exceeded", "limit of concurrent connections was reached."},</span><br><span style="color: hsl(120, 100%, 40%);">+        [MGCP_CRCX_FAIL_UNKNOWN_CALLID] = {"crcx:unkown_callid", "unknown CallId in CRCX command."},</span><br><span style="color: hsl(120, 100%, 40%);">+      [MGCP_CRCX_FAIL_ALLOC_CONN] = {"crcx:alloc_conn_fail", "connection allocation failure."},</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_NO_REMOTE_CONN_DESC] = {"crcx:no_remote_conn_desc", "no opposite end specified for connection."},</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_START_RTP] = {"crcx:start_rtp_failure", "failure to start RTP processing."},</span><br><span style="color: hsl(120, 100%, 40%);">+      [MGCP_CRCX_FAIL_REJECTED_BY_POLICY] = {"crcx:conn_rejected", "connection rejected by policy."},</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%);">+const static struct rate_ctr_group_desc mgcp_crcx_ctr_group_desc = {</span><br><span style="color: hsl(120, 100%, 40%);">+       .group_name_prefix = "crcx",</span><br><span style="color: hsl(120, 100%, 40%);">+        .group_description = "crxc statistics",</span><br><span style="color: hsl(120, 100%, 40%);">+     .class_id = OSMO_STATS_CLASS_GLOBAL,</span><br><span style="color: hsl(120, 100%, 40%);">+  .num_ctr = ARRAY_SIZE(mgcp_crcx_ctr_desc),</span><br><span style="color: hsl(120, 100%, 40%);">+    .ctr_desc = mgcp_crcx_ctr_desc</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static struct msgb *handle_audit_endpoint(struct mgcp_parse_data *data);</span><br><span> static struct msgb *handle_create_con(struct mgcp_parse_data *data);</span><br><span> static struct msgb *handle_delete_con(struct mgcp_parse_data *data);</span><br><span>@@ -701,7 +724,7 @@</span><br><span> /* CRCX command handler, processes the received command */</span><br><span> static struct msgb *handle_create_con(struct mgcp_parse_data *p)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-   struct mgcp_trunk_config *tcfg;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct mgcp_trunk_config *tcfg = p->endp->tcfg;</span><br><span>        struct mgcp_endpoint *endp = p->endp;</span><br><span>     int error_code = 400;</span><br><span> </span><br><span>@@ -733,6 +756,7 @@</span><br><span>                      /* It is illegal to send a connection identifier</span><br><span>                      * together with a CRCX, the MGW will assign the</span><br><span>                      * connection identifier by itself on CRCX */</span><br><span style="color: hsl(120, 100%, 40%);">+                 rate_ctr_inc(&tcfg->mgcp_crcx_ctr_group->ctr[MGCP_CRCX_FAIL_BAD_ACTION]);</span><br><span>                  return create_err_response(NULL, 523, "CRCX", p->trans);</span><br><span>                        break;</span><br><span>               case 'M':</span><br><span>@@ -759,19 +783,19 @@</span><br><span>                    LOGP(DLMGCP, LOGL_NOTICE,</span><br><span>                         "CRCX: endpoint:%x unhandled option: '%c'/%d\n",</span><br><span>                           ENDPOINT_NUMBER(endp), *line, *line);</span><br><span style="color: hsl(120, 100%, 40%);">+                    rate_ctr_inc(&tcfg->mgcp_crcx_ctr_group->ctr[MGCP_CRCX_FAIL_UNHANDLED_PARAM]);</span><br><span>                     return create_err_response(NULL, 539, "CRCX", p->trans);</span><br><span>                        break;</span><br><span>               }</span><br><span>    }</span><br><span> </span><br><span> mgcp_header_done:</span><br><span style="color: hsl(0, 100%, 40%);">-      tcfg = p->endp->tcfg;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>  /* Check parameters */</span><br><span>       if (!callid) {</span><br><span>               LOGP(DLMGCP, LOGL_ERROR,</span><br><span>                  "CRCX: endpoint:%x insufficient parameters, missing callid\n",</span><br><span>                     ENDPOINT_NUMBER(endp));</span><br><span style="color: hsl(120, 100%, 40%);">+          rate_ctr_inc(&tcfg->mgcp_crcx_ctr_group->ctr[MGCP_CRCX_FAIL_MISSING_CALLID]);</span><br><span>              return create_err_response(endp, 516, "CRCX", p->trans);</span><br><span>        }</span><br><span> </span><br><span>@@ -779,6 +803,7 @@</span><br><span>          LOGP(DLMGCP, LOGL_ERROR,</span><br><span>                  "CRCX: endpoint:%x insufficient parameters, missing mode\n",</span><br><span>               ENDPOINT_NUMBER(endp));</span><br><span style="color: hsl(120, 100%, 40%);">+          rate_ctr_inc(&tcfg->mgcp_crcx_ctr_group->ctr[MGCP_CRCX_FAIL_INVALID_MODE]);</span><br><span>                return create_err_response(endp, 517, "CRCX", p->trans);</span><br><span>        }</span><br><span> </span><br><span>@@ -795,6 +820,7 @@</span><br><span>          } else {</span><br><span>                     /* There is no more room for a connection, leave</span><br><span>                      * everything as it is and return with an error */</span><br><span style="color: hsl(120, 100%, 40%);">+                    rate_ctr_inc(&tcfg->mgcp_crcx_ctr_group->ctr[MGCP_CRCX_FAIL_LIMIT_EXCEEDED]);</span><br><span>                      return create_err_response(endp, 540, "CRCX", p->trans);</span><br><span>                }</span><br><span>    }</span><br><span>@@ -812,6 +838,7 @@</span><br><span>              else {</span><br><span>                       /* This is not our call, leave everything as it is and</span><br><span>                        * return with an error. */</span><br><span style="color: hsl(120, 100%, 40%);">+                   rate_ctr_inc(&tcfg->mgcp_crcx_ctr_group->ctr[MGCP_CRCX_FAIL_UNKNOWN_CALLID]);</span><br><span>                      return create_err_response(endp, 400, "CRCX", p->trans);</span><br><span>                }</span><br><span>    }</span><br><span>@@ -827,6 +854,7 @@</span><br><span>              LOGP(DLMGCP, LOGL_ERROR,</span><br><span>                  "CRCX: endpoint:0x%x unable to allocate RTP connection\n",</span><br><span>                 ENDPOINT_NUMBER(endp));</span><br><span style="color: hsl(120, 100%, 40%);">+          rate_ctr_inc(&tcfg->mgcp_crcx_ctr_group->ctr[MGCP_CRCX_FAIL_ALLOC_CONN]);</span><br><span>          goto error2;</span><br><span> </span><br><span>     }</span><br><span>@@ -890,6 +918,7 @@</span><br><span>                   "CRCX: endpoint:%x selected connection mode type requires an opposite end!\n",</span><br><span>                     ENDPOINT_NUMBER(endp));</span><br><span>                 error_code = 527;</span><br><span style="color: hsl(120, 100%, 40%);">+             rate_ctr_inc(&tcfg->mgcp_crcx_ctr_group->ctr[MGCP_CRCX_FAIL_NO_REMOTE_CONN_DESC]);</span><br><span>                 goto error2;</span><br><span>         }</span><br><span> </span><br><span>@@ -901,6 +930,7 @@</span><br><span>          LOGP(DLMGCP, LOGL_ERROR,</span><br><span>                  "CRCX: endpoint:0x%x could not start RTP processing!\n",</span><br><span>                   ENDPOINT_NUMBER(endp));</span><br><span style="color: hsl(120, 100%, 40%);">+          rate_ctr_inc(&tcfg->mgcp_crcx_ctr_group->ctr[MGCP_CRCX_FAIL_START_RTP]);</span><br><span>           goto error2;</span><br><span>         }</span><br><span> </span><br><span>@@ -915,6 +945,7 @@</span><br><span>                       "CRCX: endpoint:0x%x CRCX rejected by policy\n",</span><br><span>                           ENDPOINT_NUMBER(endp));</span><br><span>                         mgcp_endp_release(endp);</span><br><span style="color: hsl(120, 100%, 40%);">+                      rate_ctr_inc(&tcfg->mgcp_crcx_ctr_group->ctr[MGCP_CRCX_FAIL_REJECTED_BY_POLICY]);</span><br><span>                  return create_err_response(endp, 400, "CRCX", p->trans);</span><br><span>                        break;</span><br><span>               case MGCP_POLICY_DEFER:</span><br><span>@@ -942,6 +973,7 @@</span><br><span>        LOGP(DLMGCP, LOGL_NOTICE,</span><br><span>         "CRCX: endpoint:0x%x connection successfully created\n",</span><br><span>           ENDPOINT_NUMBER(endp));</span><br><span style="color: hsl(120, 100%, 40%);">+  rate_ctr_inc(&tcfg->mgcp_crcx_ctr_group->ctr[MGCP_CRCX_SUCCESS]);</span><br><span>  return create_response_with_sdp(endp, conn, "CRCX", p->trans, true);</span><br><span> error2:</span><br><span>         mgcp_endp_release(endp);</span><br><span>@@ -1396,6 +1428,28 @@</span><br><span>                                tcfg->keepalive_interval, 0);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int free_rate_counter_group(struct rate_ctr_group *rate_ctr_group)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   rate_ctr_group_free(rate_ctr_group);</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%);">+static void alloc_mgcp_crxc_rate_counters(struct mgcp_trunk_config *trunk, void *ctx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      /* FIXME: Each new rate counter group requires a unique index. At the</span><br><span style="color: hsl(120, 100%, 40%);">+  * moment we generate an index using a counter, but perhaps there is</span><br><span style="color: hsl(120, 100%, 40%);">+   * a better way of assigning indices? */</span><br><span style="color: hsl(120, 100%, 40%);">+      static unsigned int rate_ctr_index = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (trunk->mgcp_crcx_ctr_group != NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+            return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     trunk->mgcp_crcx_ctr_group = rate_ctr_group_alloc(ctx, &mgcp_crcx_ctr_group_desc, rate_ctr_index);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(trunk->mgcp_crcx_ctr_group);</span><br><span style="color: hsl(120, 100%, 40%);">+   talloc_set_destructor(trunk->mgcp_crcx_ctr_group, free_rate_counter_group);</span><br><span style="color: hsl(120, 100%, 40%);">+        rate_ctr_index++;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! allocate configuration with default values.</span><br><span>  *  (called once at startup by main function) */</span><br><span> struct mgcp_config *mgcp_config_alloc(void)</span><br><span>@@ -1433,6 +1487,7 @@</span><br><span>         cfg->trunk.audio_send_name = 1;</span><br><span>   cfg->trunk.omit_rtcp = 0;</span><br><span>         mgcp_trunk_set_keepalive(&cfg->trunk, MGCP_KEEPALIVE_ONCE);</span><br><span style="color: hsl(120, 100%, 40%);">+    alloc_mgcp_crxc_rate_counters(&cfg->trunk, cfg);</span><br><span> </span><br><span>  INIT_LLIST_HEAD(&cfg->trunks);</span><br><span> </span><br><span>@@ -1464,7 +1519,9 @@</span><br><span>    trunk->vty_number_endpoints = 33;</span><br><span>         trunk->omit_rtcp = 0;</span><br><span>     mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);</span><br><span style="color: hsl(120, 100%, 40%);">+ alloc_mgcp_crxc_rate_counters(trunk, trunk);</span><br><span>         llist_add_tail(&trunk->entry, &cfg->trunks);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         return trunk;</span><br><span> }</span><br><span> </span><br><span>@@ -1509,6 +1566,8 @@</span><br><span>       }</span><br><span> </span><br><span>        tcfg->number_endpoints = tcfg->vty_number_endpoints;</span><br><span style="color: hsl(120, 100%, 40%);">+    alloc_mgcp_crxc_rate_counters(tcfg, tcfg->cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         return 0;</span><br><span> }</span><br><span> </span><br><span>diff --git a/src/libosmo-mgcp/mgcp_vty.c b/src/libosmo-mgcp/mgcp_vty.c</span><br><span>index 75cc52f..fdcca91 100644</span><br><span>--- a/src/libosmo-mgcp/mgcp_vty.c</span><br><span>+++ b/src/libosmo-mgcp/mgcp_vty.c</span><br><span>@@ -22,6 +22,7 @@</span><br><span>  */</span><br><span> </span><br><span> #include <osmocom/core/talloc.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/vty/misc.h></span><br><span> #include <osmocom/mgcp/mgcp.h></span><br><span> #include <osmocom/mgcp/mgcp_common.h></span><br><span> #include <osmocom/mgcp/mgcp_internal.h></span><br><span>@@ -233,6 +234,11 @@</span><br><span>             if (i < cfg->number_endpoints - 1)</span><br><span>                     vty_out(vty, "%s", VTY_NEWLINE);</span><br><span>   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (show_stats && cfg->mgcp_crcx_ctr_group) {</span><br><span style="color: hsl(120, 100%, 40%);">+              vty_out(vty, "   %s:%s", cfg->mgcp_crcx_ctr_group->desc->group_description, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+          vty_out_rate_ctr_group_fmt(vty, "   %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->mgcp_crcx_ctr_group);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span> }</span><br><span> </span><br><span> #define SHOW_MGCP_STR "Display information about the MGCP Media Gateway\n"</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/11463">change 11463</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/11463"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-mgw </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: Ida82fc340d5c66180e5fe9a0d195e9be6dc64c61 </div>
<div style="display:none"> Gerrit-Change-Number: 11463 </div>
<div style="display:none"> Gerrit-PatchSet: 4 </div>
<div style="display:none"> Gerrit-Owner: Stefan Sperling <ssperling@sysmocom.de> </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: Stefan Sperling <ssperling@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: dexter <pmaier@sysmocom.de> </div>