<p>neels has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-msc/+/25076">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">implement CM Re-Establish for voice calls<br><br>Related: SYS#5130<br>Change-Id: I6fa37d6ca9fcb1637742b40e37b68d67664c9b60<br>---<br>M include/osmocom/msc/gsm_data.h<br>M include/osmocom/msc/msc_common.h<br>M include/osmocom/msc/vlr.h<br>M src/libmsc/gsm_04_08.c<br>M src/libmsc/msc_a.c<br>5 files changed, 135 insertions(+), 2 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-msc refs/changes/76/25076/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/msc/gsm_data.h b/include/osmocom/msc/gsm_data.h</span><br><span>index 1870804..b87afa0 100644</span><br><span>--- a/include/osmocom/msc/gsm_data.h</span><br><span>+++ b/include/osmocom/msc/gsm_data.h</span><br><span>@@ -44,6 +44,8 @@</span><br><span>   MSC_CTR_CM_SERVICE_REQUEST_ACCEPTED,</span><br><span>         MSC_CTR_PAGING_RESP_REJECTED,</span><br><span>        MSC_CTR_PAGING_RESP_ACCEPTED,</span><br><span style="color: hsl(120, 100%, 40%);">+ MSC_CTR_CM_RE_ESTABLISH_REQ_ACCEPTED,</span><br><span style="color: hsl(120, 100%, 40%);">+ MSC_CTR_CM_RE_ESTABLISH_REQ_REJECTED,</span><br><span>        MSC_CTR_SMS_SUBMITTED,</span><br><span>       MSC_CTR_SMS_NO_RECEIVER,</span><br><span>     MSC_CTR_SMS_DELIVERED,</span><br><span>@@ -76,6 +78,8 @@</span><br><span>   [MSC_CTR_CM_SERVICE_REQUEST_ACCEPTED] = {"cm_service_request:accepted", "Accepted CM Service Requests."},</span><br><span>        [MSC_CTR_PAGING_RESP_REJECTED] =        {"paging_resp:rejected", "Rejected Paging Responses."},</span><br><span>  [MSC_CTR_PAGING_RESP_ACCEPTED] =        {"paging_resp:accepted", "Accepted Paging Responses."},</span><br><span style="color: hsl(120, 100%, 40%);">+   [MSC_CTR_CM_RE_ESTABLISH_REQ_REJECTED] = {"cm_re_establish_request:rejected", "Rejected CM Re-Establishing Requests."},</span><br><span style="color: hsl(120, 100%, 40%);">+   [MSC_CTR_CM_RE_ESTABLISH_REQ_ACCEPTED] = {"cm_re_establish_request:accepted", "Accepted CM Re-Establishing Requests."},</span><br><span>  [MSC_CTR_SMS_SUBMITTED] =               {"sms:submitted", "Total MO SMS received from the MS."},</span><br><span>         [MSC_CTR_SMS_NO_RECEIVER] =             {"sms:no_receiver", "Failed MO SMS delivery attempts (no receiver found)."},</span><br><span>     [MSC_CTR_SMS_DELIVER_UNKNOWN_ERROR] =   {"sms:deliver_unknown_error", "Failed MO SMS delivery attempts (other reason)."},</span><br><span>diff --git a/include/osmocom/msc/msc_common.h b/include/osmocom/msc/msc_common.h</span><br><span>index e7ac559..f3fb0e0 100644</span><br><span>--- a/include/osmocom/msc/msc_common.h</span><br><span>+++ b/include/osmocom/msc/msc_common.h</span><br><span>@@ -41,6 +41,7 @@</span><br><span>       COMPLETE_LAYER3_LU,</span><br><span>  COMPLETE_LAYER3_CM_SERVICE_REQ,</span><br><span>      COMPLETE_LAYER3_PAGING_RESP,</span><br><span style="color: hsl(120, 100%, 40%);">+  COMPLETE_LAYER3_CM_RE_ESTABLISH_REQ,</span><br><span> };</span><br><span> </span><br><span> extern const struct value_string complete_layer3_type_names[];</span><br><span>diff --git a/include/osmocom/msc/vlr.h b/include/osmocom/msc/vlr.h</span><br><span>index 3273333..f12e906 100644</span><br><span>--- a/include/osmocom/msc/vlr.h</span><br><span>+++ b/include/osmocom/msc/vlr.h</span><br><span>@@ -444,6 +444,7 @@</span><br><span>      VLR_PR_ARQ_T_INVALID = 0, /* to guard against unset vars */</span><br><span>  VLR_PR_ARQ_T_CM_SERV_REQ,</span><br><span>    VLR_PR_ARQ_T_PAGING_RESP,</span><br><span style="color: hsl(120, 100%, 40%);">+     VLR_PR_ARQ_T_CM_RE_ESTABLISH_REQ,</span><br><span>    /* FIXME: differentiate between services of 24.008 10.5.3.3 */</span><br><span> };</span><br><span> </span><br><span>diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c</span><br><span>index fb450e6..76d0bbc 100644</span><br><span>--- a/src/libmsc/gsm_04_08.c</span><br><span>+++ b/src/libmsc/gsm_04_08.c</span><br><span>@@ -48,11 +48,13 @@</span><br><span> #include <osmocom/core/talloc.h></span><br><span> #include <osmocom/core/utils.h></span><br><span> #include <osmocom/core/byteswap.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/fsm.h></span><br><span> #include <osmocom/gsm/tlv.h></span><br><span> #include <osmocom/crypt/auth.h></span><br><span> </span><br><span> #include <osmocom/msc/msub.h></span><br><span> #include <osmocom/msc/msc_roles.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/msc/call_leg.h></span><br><span> </span><br><span> #include <assert.h></span><br><span> </span><br><span>@@ -824,17 +826,128 @@</span><br><span> /* Receive a CM Re-establish Request */</span><br><span> static int gsm48_rx_cm_reest_req(struct msc_a *msc_a, struct msgb *msg)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+       struct gsm_network *net = msc_a_net(msc_a);</span><br><span style="color: hsl(120, 100%, 40%);">+   struct gsm48_hdr *gh;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_service_request *req;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct gsm48_classmark2 *cm2;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *cm2_buf, cm2_len;</span><br><span style="color: hsl(120, 100%, 40%);">+    bool is_utran;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct vlr_subscr *vsub;</span><br><span>     struct osmo_mobile_identity mi;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct msub *prev_msub;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct msc_a *prev_msc_a;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  int rc = osmo_mobile_identity_decode_from_l3(&mi, msg, false);</span><br><span>   if (rc) {</span><br><span>            LOGP(DMM, LOGL_ERROR, "CM RE-ESTABLISH REQUEST: cannot decode Mobile Identity\n");</span><br><span>                 return -EINVAL;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ msc_a->complete_layer3_type = COMPLETE_LAYER3_CM_RE_ESTABLISH_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+ msub_update_id_from_mi(msc_a->c.msub, &mi);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         DEBUGP(DMM, "<- CM RE-ESTABLISH REQUEST %s\n", osmo_mobile_identity_to_str_c(OTC_SELECT, &mi));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    /* we don't support CM call re-establishment */</span><br><span style="color: hsl(0, 100%, 40%);">-     return msc_gsm48_tx_mm_serv_rej(msc_a, GSM48_REJECT_SRV_OPT_NOT_SUPPORTED);</span><br><span style="color: hsl(120, 100%, 40%);">+   gh = (struct gsm48_hdr *) msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+       req = (struct gsm48_service_request *) gh->data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Unfortunately in Phase1 the Classmark2 length is variable, so we cannot</span><br><span style="color: hsl(120, 100%, 40%);">+     * just use gsm48_service_request struct, and need to parse it manually. */</span><br><span style="color: hsl(120, 100%, 40%);">+   cm2_len = gh->data[1];</span><br><span style="color: hsl(120, 100%, 40%);">+     cm2_buf = gh->data + 2;</span><br><span style="color: hsl(120, 100%, 40%);">+    cm2 = (struct gsm48_classmark2 *) cm2_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Prevent buffer overrun: check the length of Classmark2 */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (cm2_buf + cm2_len > msg->tail) {</span><br><span style="color: hsl(120, 100%, 40%);">+            LOG_MSC_A(msc_a, LOGL_ERROR, "Rx CM SERVICE REQUEST: Classmark2 "</span><br><span style="color: hsl(120, 100%, 40%);">+                                        "length=%u is too big\n", cm2_len);</span><br><span style="color: hsl(120, 100%, 40%);">+            return msc_gsm48_tx_mm_serv_rej(msc_a, GSM48_REJECT_INCORRECT_MESSAGE);</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%);">+   /* Look up the other, previously active connection for this subscriber */</span><br><span style="color: hsl(120, 100%, 40%);">+     vsub = vlr_subscr_find_by_mi(net->vlr, &mi, __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+ prev_msub = msub_for_vsub(vsub);</span><br><span style="color: hsl(120, 100%, 40%);">+      prev_msc_a = msub_msc_a(prev_msub);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!vsub || !prev_msub || !prev_msc_a) {</span><br><span style="color: hsl(120, 100%, 40%);">+             LOG_MSC_A(msc_a, LOGL_ERROR, "CM Re-Establish Request for unknown subscriber: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                          osmo_mobile_identity_to_str_c(OTC_SELECT, &mi));</span><br><span style="color: hsl(120, 100%, 40%);">+                if (vsub)</span><br><span style="color: hsl(120, 100%, 40%);">+                     vlr_subscr_put(vsub, __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+               return msc_gsm48_tx_mm_serv_rej(msc_a, GSM48_REJECT_IMSI_UNKNOWN_IN_VLR);</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%);">+   LOG_MSC_A(msc_a, LOGL_NOTICE, "New conn requesting Re-Establishment\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    LOG_MSC_A(prev_msc_a, LOGL_NOTICE, "Old conn matching Re-Establishment request (%s)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+               osmo_use_count_to_str_c(OTC_SELECT, &prev_msc_a->use_count));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!prev_msc_a->cc.call_leg || !prev_msc_a->cc.active_trans) {</span><br><span style="color: hsl(120, 100%, 40%);">+         LOG_MSC_A(msc_a, LOGL_ERROR, "CM Re-Establish Request only supported for voice calls\n");</span><br><span style="color: hsl(120, 100%, 40%);">+           if (vsub)</span><br><span style="color: hsl(120, 100%, 40%);">+                     vlr_subscr_put(vsub, __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+               return msc_gsm48_tx_mm_serv_rej(msc_a, GSM48_REJECT_NETWORK_FAILURE);</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%);">+   msc_a_get(prev_msc_a, __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Move the call_leg and active CC trans over to the new msc_a */</span><br><span style="color: hsl(120, 100%, 40%);">+     call_leg_reparent(prev_msc_a->cc.call_leg,</span><br><span style="color: hsl(120, 100%, 40%);">+                   msc_a->c.fi,</span><br><span style="color: hsl(120, 100%, 40%);">+                       MSC_EV_CALL_LEG_TERM,</span><br><span style="color: hsl(120, 100%, 40%);">+                         MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE,</span><br><span style="color: hsl(120, 100%, 40%);">+                     MSC_EV_CALL_LEG_RTP_COMPLETE);</span><br><span style="color: hsl(120, 100%, 40%);">+      msc_a->cc.call_leg = prev_msc_a->cc.call_leg;</span><br><span style="color: hsl(120, 100%, 40%);">+   prev_msc_a->cc.call_leg = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  msc_a->cc.active_trans = prev_msc_a->cc.active_trans;</span><br><span style="color: hsl(120, 100%, 40%);">+   msc_a->cc.active_trans->msc_a = msc_a;</span><br><span style="color: hsl(120, 100%, 40%);">+  msc_a_get(msc_a, MSC_A_USE_CC);</span><br><span style="color: hsl(120, 100%, 40%);">+       prev_msc_a->cc.active_trans = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+        msc_a_put(prev_msc_a, MSC_A_USE_CC);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Dis-associate the VLR subscriber from the previous msc_a, so that we can start a new Process Access Request</span><br><span style="color: hsl(120, 100%, 40%);">+         * on the new msc_a. */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (vsub->proc_arq_fsm) {</span><br><span style="color: hsl(120, 100%, 40%);">+          osmo_fsm_inst_term(vsub->proc_arq_fsm, OSMO_FSM_TERM_REGULAR, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+               vsub->proc_arq_fsm = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (prev_msub->vsub) {</span><br><span style="color: hsl(120, 100%, 40%);">+             vlr_subscr_put(prev_msub->vsub, VSUB_USE_MSUB);</span><br><span style="color: hsl(120, 100%, 40%);">+            prev_msub->vsub = 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%);">+   /* Clear the previous conn.</span><br><span style="color: hsl(120, 100%, 40%);">+    * FIXME: we are clearing the previous conn before having authenticated the new conn. That means anyone can send</span><br><span style="color: hsl(120, 100%, 40%);">+       * CM Re-Establishing requests with arbitrary mobile identities without having to authenticate, and can freely</span><br><span style="color: hsl(120, 100%, 40%);">+         * Clear any connections at will. */</span><br><span style="color: hsl(120, 100%, 40%);">+  msc_a_release_cn(prev_msc_a);</span><br><span style="color: hsl(120, 100%, 40%);">+ msc_a_put(prev_msc_a, __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+      prev_msc_a = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Kick off Authentication and Ciphering for the new conn. */</span><br><span style="color: hsl(120, 100%, 40%);">+ is_utran = (msc_a->c.ran->type == OSMO_RAT_UTRAN_IU);</span><br><span style="color: hsl(120, 100%, 40%);">+   vlr_proc_acc_req(msc_a->c.fi,</span><br><span style="color: hsl(120, 100%, 40%);">+                       MSC_A_EV_AUTHENTICATED, MSC_A_EV_CN_CLOSE, NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+                      net->vlr, msc_a,</span><br><span style="color: hsl(120, 100%, 40%);">+                   VLR_PR_ARQ_T_CM_RE_ESTABLISH_REQ, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                  &mi, &msc_a->via_cell.lai,</span><br><span style="color: hsl(120, 100%, 40%);">+                         is_utran || net->authentication_required,</span><br><span style="color: hsl(120, 100%, 40%);">+                  is_utran ? net->uea_encryption : net->a5_encryption_mask > 0x01,</span><br><span style="color: hsl(120, 100%, 40%);">+                     req->cipher_key_seq,</span><br><span style="color: hsl(120, 100%, 40%);">+                       osmo_gsm48_classmark2_is_r99(cm2, cm2_len),</span><br><span style="color: hsl(120, 100%, 40%);">+                   is_utran);</span><br><span style="color: hsl(120, 100%, 40%);">+   vlr_subscr_put(vsub, __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* From vlr_proc_acc_req() we expect an implicit dispatch of PR_ARQ_E_START, and we expect</span><br><span style="color: hsl(120, 100%, 40%);">+     * msc_vlr_subscr_assoc() to already have been called and completed. Has an error occurred? */</span><br><span style="color: hsl(120, 100%, 40%);">+        vsub = msc_a_vsub(msc_a);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!vsub) {</span><br><span style="color: hsl(120, 100%, 40%);">+          LOG_MSC_A(msc_a, LOGL_ERROR, "subscriber not allowed to do a CM Service Request\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                return -EIO;</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%);">+   vsub->classmark.classmark2 = *cm2;</span><br><span style="color: hsl(120, 100%, 40%);">+ vsub->classmark.classmark2_len = cm2_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  return 0;</span><br><span> }</span><br><span> </span><br><span> static int gsm48_rx_mm_imsi_detach_ind(struct msc_a *msc_a, struct msgb *msg)</span><br><span>diff --git a/src/libmsc/msc_a.c b/src/libmsc/msc_a.c</span><br><span>index 0bc7b26..7a1ace0 100644</span><br><span>--- a/src/libmsc/msc_a.c</span><br><span>+++ b/src/libmsc/msc_a.c</span><br><span>@@ -120,6 +120,10 @@</span><br><span>      case COMPLETE_LAYER3_PAGING_RESP:</span><br><span>            rate_ctr_inc(rate_ctr_group_get_ctr(net->msc_ctrs, conn_accepted ? MSC_CTR_PAGING_RESP_ACCEPTED : MSC_CTR_PAGING_RESP_REJECTED));</span><br><span>                 break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case COMPLETE_LAYER3_CM_RE_ESTABLISH_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+             rate_ctr_inc(rate_ctr_group_get_ctr(net->msc_ctrs, conn_accepted</span><br><span style="color: hsl(120, 100%, 40%);">+                                               ? MSC_CTR_CM_RE_ESTABLISH_REQ_ACCEPTED : MSC_CTR_CM_RE_ESTABLISH_REQ_REJECTED));</span><br><span style="color: hsl(120, 100%, 40%);">+          break;</span><br><span>       default:</span><br><span>             break;</span><br><span>       }</span><br><span>@@ -151,6 +155,15 @@</span><br><span> </span><br><span>         if (msc_a->complete_layer3_type == COMPLETE_LAYER3_LU)</span><br><span>            msc_a_put(msc_a, MSC_A_USE_LOCATION_UPDATING);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (msc_a->complete_layer3_type == COMPLETE_LAYER3_CM_RE_ESTABLISH_REQ) {</span><br><span style="color: hsl(120, 100%, 40%);">+          /* Trigger new Assignment to recommence the voice call. A little dance here because normally we verify</span><br><span style="color: hsl(120, 100%, 40%);">+                 * that no CC trans is already active. */</span><br><span style="color: hsl(120, 100%, 40%);">+             struct gsm_trans *cc_trans = msc_a->cc.active_trans;</span><br><span style="color: hsl(120, 100%, 40%);">+               msc_a->cc.active_trans = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+             osmo_fsm_inst_dispatch(msc_a->c.fi, MSC_A_EV_TRANSACTION_ACCEPTED, cc_trans);</span><br><span style="color: hsl(120, 100%, 40%);">+              msc_a_try_call_assignment(cc_trans);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span> }</span><br><span> </span><br><span> bool msc_a_is_accepted(const struct msc_a *msc_a)</span><br><span>@@ -1092,6 +1105,7 @@</span><br><span>      { COMPLETE_LAYER3_LU, "LU" },</span><br><span>      { COMPLETE_LAYER3_CM_SERVICE_REQ, "CM_SERVICE_REQ" },</span><br><span>      { COMPLETE_LAYER3_PAGING_RESP, "PAGING_RESP" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { COMPLETE_LAYER3_CM_RE_ESTABLISH_REQ, "CM_RE_ESTABLISH_REQ" },</span><br><span>    { 0, NULL }</span><br><span> };</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-msc/+/25076">change 25076</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/osmo-msc/+/25076"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-msc </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I6fa37d6ca9fcb1637742b40e37b68d67664c9b60 </div>
<div style="display:none"> Gerrit-Change-Number: 25076 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>