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

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">cosmetic: move RR functions from bsc_api.c to gsm_04_08_rr.c<br><br>Rationale: bsc_api.c used to be a kind of kitchen sink for various<br>implementations, we want to dissolve it. Also, combining 0808 and 0408 in the<br>same c file causes "weird" linking dependencies for utility and test programs.<br><br>bsc_api.c will be completely dissolved in upcoming<br>Ib7ce026b52d4ba3e53a8b2824e74ea92432c48c5.<br><br>Change-Id: Ie8ee334145bf7bc3a601d395ea7ab9b2009b61c7<br>---<br>M include/osmocom/bsc/bsc_api.h<br>M include/osmocom/bsc/gsm_04_08_rr.h<br>M src/osmo-bsc/bsc_api.c<br>M src/osmo-bsc/gsm_04_08_rr.c<br>4 files changed, 309 insertions(+), 307 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/bsc/bsc_api.h b/include/osmocom/bsc/bsc_api.h</span><br><span>index a90268b..9e2b44e 100644</span><br><span>--- a/include/osmocom/bsc/bsc_api.h</span><br><span>+++ b/include/osmocom/bsc/bsc_api.h</span><br><span>@@ -28,5 +28,4 @@</span><br><span>                unsigned int mi_len, uint8_t *mi, int chan_type);</span><br><span> int gsm0808_clear(struct gsm_subscriber_connection *conn);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id);</span><br><span> #endif</span><br><span>diff --git a/include/osmocom/bsc/gsm_04_08_rr.h b/include/osmocom/bsc/gsm_04_08_rr.h</span><br><span>index 4349a37..69cb6ea 100644</span><br><span>--- a/include/osmocom/bsc/gsm_04_08_rr.h</span><br><span>+++ b/include/osmocom/bsc/gsm_04_08_rr.h</span><br><span>@@ -41,3 +41,5 @@</span><br><span> }</span><br><span> </span><br><span> uint64_t str_to_imsi(const char *imsi_str);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id);</span><br><span>diff --git a/src/osmo-bsc/bsc_api.c b/src/osmo-bsc/bsc_api.c</span><br><span>index 2ce8d3b..92b64e4 100644</span><br><span>--- a/src/osmo-bsc/bsc_api.c</span><br><span>+++ b/src/osmo-bsc/bsc_api.c</span><br><span>@@ -195,312 +195,6 @@</span><br><span>         return rsl_paging_cmd(bts, page_group, mi_len, mi, chan_type, false);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void handle_ass_compl(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(0, 100%, 40%);">-                           struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-    enum gsm48_rr_cause cause;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      /* Expecting gsm48_hdr + cause value */</span><br><span style="color: hsl(0, 100%, 40%);">- if (msgb_l3len(msg) != sizeof(*gh) + 1) {</span><br><span style="color: hsl(0, 100%, 40%);">-               LOGPLCHAN(msg->lchan, DRR, LOGL_ERROR,</span><br><span style="color: hsl(0, 100%, 40%);">-                         "RR Assignment Complete: length invalid: %u, expected %zu\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                         msgb_l3len(msg), sizeof(*gh) + 1);</span><br><span style="color: hsl(0, 100%, 40%);">-            return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       cause = gh->data[0];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG, "ASSIGNMENT COMPLETE cause = %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-           rr_cause_name(cause));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        if (conn->ho) {</span><br><span style="color: hsl(0, 100%, 40%);">-              struct lchan_signal_data sig = {</span><br><span style="color: hsl(0, 100%, 40%);">-                        .lchan = msg->lchan,</span><br><span style="color: hsl(0, 100%, 40%);">-         };</span><br><span style="color: hsl(0, 100%, 40%);">-              osmo_signal_dispatch(SS_LCHAN, S_LCHAN_ASSIGNMENT_COMPL, &sig);</span><br><span style="color: hsl(0, 100%, 40%);">-             /* FIXME: release old channel */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                /* send pending messages, if any */</span><br><span style="color: hsl(0, 100%, 40%);">-             gscon_dtap_queue_flush(conn, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (conn->secondary_lchan != msg->lchan) {</span><br><span style="color: hsl(0, 100%, 40%);">-                LOGPLCHAN(msg->lchan, DRR, LOGL_ERROR,</span><br><span style="color: hsl(0, 100%, 40%);">-                         "RR Assignment Complete does not match conn's secondary lchan.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-             return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       lchan_release(conn->lchan, 0, RSL_REL_LOCAL_END);</span><br><span style="color: hsl(0, 100%, 40%);">-    conn->lchan = conn->secondary_lchan;</span><br><span style="color: hsl(0, 100%, 40%);">-      conn->secondary_lchan = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        /* send pending messages, if any */</span><br><span style="color: hsl(0, 100%, 40%);">-     gscon_dtap_queue_flush(conn, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        if (is_ipaccess_bts(conn_get_bts(conn)) && conn->lchan->tch_mode != GSM48_CMODE_SIGN)</span><br><span style="color: hsl(0, 100%, 40%);">-             rsl_ipacc_crcx(conn->lchan);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- bsc_assign_compl(conn, cause);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void handle_ass_fail(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(0, 100%, 40%);">-                          struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-  uint8_t *rr_failure;</span><br><span style="color: hsl(0, 100%, 40%);">-    struct gsm48_hdr *gh;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   if (conn->ho) {</span><br><span style="color: hsl(0, 100%, 40%);">-              struct lchan_signal_data sig;</span><br><span style="color: hsl(0, 100%, 40%);">-           struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-            LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG, "ASSIGNMENT FAILED cause = %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                     rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               sig.lchan = msg->lchan;</span><br><span style="color: hsl(0, 100%, 40%);">-              sig.mr = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-          osmo_signal_dispatch(SS_LCHAN, S_LCHAN_ASSIGNMENT_FAIL, &sig);</span><br><span style="color: hsl(0, 100%, 40%);">-              /* FIXME: release allocated new channel */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-              /* send pending messages, if any */</span><br><span style="color: hsl(0, 100%, 40%);">-             gscon_dtap_queue_flush(conn, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (conn->lchan != msg->lchan) {</span><br><span style="color: hsl(0, 100%, 40%);">-          LOGPLCHAN(msg->lchan, DMSC, LOGL_ERROR,</span><br><span style="color: hsl(0, 100%, 40%);">-                        "Assignment failure should occur on primary lchan.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-             return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* stop the timer and release it */</span><br><span style="color: hsl(0, 100%, 40%);">-     if (conn->secondary_lchan) {</span><br><span style="color: hsl(0, 100%, 40%);">-         lchan_release(conn->secondary_lchan, 0, RSL_REL_LOCAL_END);</span><br><span style="color: hsl(0, 100%, 40%);">-          conn->secondary_lchan = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-        }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* send pending messages, if any */</span><br><span style="color: hsl(0, 100%, 40%);">-     gscon_dtap_queue_flush(conn, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        gh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-      if (msgb_l3len(msg) - sizeof(*gh) != 1) {</span><br><span style="color: hsl(0, 100%, 40%);">-               LOGPLCHAN(conn->lchan, DMSC, LOGL_ERROR, "assignment failure unhandled: %zu\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                      msgb_l3len(msg) - sizeof(*gh));</span><br><span style="color: hsl(0, 100%, 40%);">-               rr_failure = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-      } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                rr_failure = &gh->data[0];</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc_assign_fail(conn, GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, rr_failure);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void handle_classmark_chg(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(0, 100%, 40%);">-                               struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-     struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-    unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);</span><br><span style="color: hsl(0, 100%, 40%);">-       uint8_t cm2_len, cm3_len = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-   uint8_t *cm2, *cm3 = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG, "CLASSMARK CHANGE ");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* classmark 2 */</span><br><span style="color: hsl(0, 100%, 40%);">-       cm2_len = gh->data[0];</span><br><span style="color: hsl(0, 100%, 40%);">-       cm2 = &gh->data[1];</span><br><span style="color: hsl(0, 100%, 40%);">-      DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        if (payload_len > cm2_len + 1) {</span><br><span style="color: hsl(0, 100%, 40%);">-             /* we must have a classmark3 */</span><br><span style="color: hsl(0, 100%, 40%);">-         if (gh->data[cm2_len+1] != 0x20) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   DEBUGPC(DRR, "ERR CM3 TAG\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                        return;</span><br><span style="color: hsl(0, 100%, 40%);">-         }</span><br><span style="color: hsl(0, 100%, 40%);">-               if (cm2_len > 3) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   DEBUGPC(DRR, "CM2 too long!\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                      return;</span><br><span style="color: hsl(0, 100%, 40%);">-         }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               cm3_len = gh->data[cm2_len+2];</span><br><span style="color: hsl(0, 100%, 40%);">-               cm3 = &gh->data[cm2_len+3];</span><br><span style="color: hsl(0, 100%, 40%);">-              if (cm3_len > 14) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);</span><br><span style="color: hsl(0, 100%, 40%);">-                      return;</span><br><span style="color: hsl(0, 100%, 40%);">-         }</span><br><span style="color: hsl(0, 100%, 40%);">-               DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-       bsc_cm_update(conn, cm2, cm2_len, cm3, cm3_len);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Chapter 9.1.16 Handover complete */</span><br><span style="color: hsl(0, 100%, 40%);">-static void handle_rr_ho_compl(struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        struct lchan_signal_data sig;</span><br><span style="color: hsl(0, 100%, 40%);">-   struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG,</span><br><span style="color: hsl(0, 100%, 40%);">-                 "HANDOVER COMPLETE cause = %s\n", rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   sig.lchan = msg->lchan;</span><br><span style="color: hsl(0, 100%, 40%);">-      sig.mr = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-  osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_COMPL, &sig);</span><br><span style="color: hsl(0, 100%, 40%);">-       /* FIXME: release old channel */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        /* send pending messages, if any */</span><br><span style="color: hsl(0, 100%, 40%);">-     gscon_dtap_queue_flush(msg->lchan->conn, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Chapter 9.1.17 Handover Failure */</span><br><span style="color: hsl(0, 100%, 40%);">-static void handle_rr_ho_fail(struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        struct lchan_signal_data sig;</span><br><span style="color: hsl(0, 100%, 40%);">-   struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    /* Log on both RR and HO categories: it is an RR message, but is still quite important when</span><br><span style="color: hsl(0, 100%, 40%);">-      * filtering on HO. */</span><br><span style="color: hsl(0, 100%, 40%);">-  LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG,</span><br><span style="color: hsl(0, 100%, 40%);">-                 "HANDOVER FAILED cause = %s\n", rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(0, 100%, 40%);">-     LOGPLCHAN(msg->lchan, DHO, LOGL_DEBUG,</span><br><span style="color: hsl(0, 100%, 40%);">-                 "HANDOVER FAILED cause = %s\n", rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     sig.lchan = msg->lchan;</span><br><span style="color: hsl(0, 100%, 40%);">-      sig.mr = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-  osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_FAIL, &sig);</span><br><span style="color: hsl(0, 100%, 40%);">-        /* FIXME: release allocated new channel */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      /* send pending messages, if any */</span><br><span style="color: hsl(0, 100%, 40%);">-     gscon_dtap_queue_flush(msg->lchan->conn, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void dispatch_dtap(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(0, 100%, 40%);">-                      uint8_t link_id, struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   struct gsm48_hdr *gh;</span><br><span style="color: hsl(0, 100%, 40%);">-   uint8_t pdisc;</span><br><span style="color: hsl(0, 100%, 40%);">-  uint8_t msg_type;</span><br><span style="color: hsl(0, 100%, 40%);">-       int rc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (msgb_l3len(msg) < sizeof(*gh)) {</span><br><span style="color: hsl(0, 100%, 40%);">-         LOGP(DMSC, LOGL_ERROR, "(%s) Message too short for a GSM48 header.\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                     bsc_subscr_name(conn->bsub));</span><br><span style="color: hsl(0, 100%, 40%);">-           return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       gh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-      pdisc = gsm48_hdr_pdisc(gh);</span><br><span style="color: hsl(0, 100%, 40%);">-    msg_type = gsm48_hdr_msg_type(gh);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      /* the idea is to handle all RR messages here, and only hand</span><br><span style="color: hsl(0, 100%, 40%);">-     * MM/CC/SMS-CP/LCS up to the MSC.  Some messages like PAGING</span><br><span style="color: hsl(0, 100%, 40%);">-    * RESPONSE or CM SERVICE REQUEST will not be covered here, as</span><br><span style="color: hsl(0, 100%, 40%);">-   * they are only possible in the first L3 message of each L2</span><br><span style="color: hsl(0, 100%, 40%);">-     * channel, i.e. 'conn' will not exist and gsm0408_rcvmsg()</span><br><span style="color: hsl(0, 100%, 40%);">-      * will call api->compl_l3() for it */</span><br><span style="color: hsl(0, 100%, 40%);">-       switch (pdisc) {</span><br><span style="color: hsl(0, 100%, 40%);">-        case GSM48_PDISC_RR:</span><br><span style="color: hsl(0, 100%, 40%);">-            switch (msg_type) {</span><br><span style="color: hsl(0, 100%, 40%);">-             case GSM48_MT_RR_GPRS_SUSP_REQ:</span><br><span style="color: hsl(0, 100%, 40%);">-                 LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG,</span><br><span style="color: hsl(0, 100%, 40%);">-                                 "%s\n", gsm48_rr_msg_name(GSM48_MT_RR_GPRS_SUSP_REQ));</span><br><span style="color: hsl(0, 100%, 40%);">-                      break;</span><br><span style="color: hsl(0, 100%, 40%);">-          case GSM48_MT_RR_STATUS:</span><br><span style="color: hsl(0, 100%, 40%);">-                        LOGPLCHAN(msg->lchan, DRR, LOGL_NOTICE,</span><br><span style="color: hsl(0, 100%, 40%);">-                                "%s (cause: %s)\n", gsm48_rr_msg_name(GSM48_MT_RR_STATUS),</span><br><span style="color: hsl(0, 100%, 40%);">-                            rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(0, 100%, 40%);">-                       break;</span><br><span style="color: hsl(0, 100%, 40%);">-          case GSM48_MT_RR_MEAS_REP:</span><br><span style="color: hsl(0, 100%, 40%);">-                      /* This shouldn't actually end up here, as RSL treats</span><br><span style="color: hsl(0, 100%, 40%);">-                       * L3 Info of 08.58 MEASUREMENT REPORT different by calling</span><br><span style="color: hsl(0, 100%, 40%);">-                      * directly into gsm48_parse_meas_rep */</span><br><span style="color: hsl(0, 100%, 40%);">-                 LOGPLCHAN(msg->lchan, DMEAS, LOGL_ERROR,</span><br><span style="color: hsl(0, 100%, 40%);">-                               "DIRECT GSM48 MEASUREMENT REPORT ?!?\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                   gsm48_tx_rr_status(conn, GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT);</span><br><span style="color: hsl(0, 100%, 40%);">-                     break;</span><br><span style="color: hsl(0, 100%, 40%);">-          case GSM48_MT_RR_HANDO_COMPL:</span><br><span style="color: hsl(0, 100%, 40%);">-                   handle_rr_ho_compl(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-                        break;</span><br><span style="color: hsl(0, 100%, 40%);">-          case GSM48_MT_RR_HANDO_FAIL:</span><br><span style="color: hsl(0, 100%, 40%);">-                    handle_rr_ho_fail(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-                 break;</span><br><span style="color: hsl(0, 100%, 40%);">-          case GSM48_MT_RR_CIPH_M_COMPL:</span><br><span style="color: hsl(0, 100%, 40%);">-                  bsc_cipher_mode_compl(conn, msg, conn->lchan->encr.alg_id);</span><br><span style="color: hsl(0, 100%, 40%);">-                       break;</span><br><span style="color: hsl(0, 100%, 40%);">-          case GSM48_MT_RR_ASS_COMPL:</span><br><span style="color: hsl(0, 100%, 40%);">-                     handle_ass_compl(conn, msg);</span><br><span style="color: hsl(0, 100%, 40%);">-                    break;</span><br><span style="color: hsl(0, 100%, 40%);">-          case GSM48_MT_RR_ASS_FAIL:</span><br><span style="color: hsl(0, 100%, 40%);">-                      handle_ass_fail(conn, msg);</span><br><span style="color: hsl(0, 100%, 40%);">-                     break;</span><br><span style="color: hsl(0, 100%, 40%);">-          case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:</span><br><span style="color: hsl(0, 100%, 40%);">-                   rc = gsm48_rx_rr_modif_ack(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-                        if (rc < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-                          bsc_assign_fail(conn, GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-                 else</span><br><span style="color: hsl(0, 100%, 40%);">-                            bsc_assign_compl(conn, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-                      break;</span><br><span style="color: hsl(0, 100%, 40%);">-          case GSM48_MT_RR_CLSM_CHG:</span><br><span style="color: hsl(0, 100%, 40%);">-                      handle_classmark_chg(conn, msg);</span><br><span style="color: hsl(0, 100%, 40%);">-                        break;</span><br><span style="color: hsl(0, 100%, 40%);">-          case GSM48_MT_RR_APP_INFO:</span><br><span style="color: hsl(0, 100%, 40%);">-                      /* Passing RR APP INFO to MSC, not quite</span><br><span style="color: hsl(0, 100%, 40%);">-                         * according to spec */</span><br><span style="color: hsl(0, 100%, 40%);">-                 bsc_dtap(conn, link_id, msg);</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%);">-                        /* Drop unknown RR message */</span><br><span style="color: hsl(0, 100%, 40%);">-                   LOGPLCHAN(msg->lchan, DRR, LOGL_NOTICE,</span><br><span style="color: hsl(0, 100%, 40%);">-                                "Dropping %s 04.08 RR message\n", gsm48_rr_msg_name(msg_type));</span><br><span style="color: hsl(0, 100%, 40%);">-                     gsm48_tx_rr_status(conn, GSM48_RR_CAUSE_MSG_TYPE_N);</span><br><span style="color: hsl(0, 100%, 40%);">-                    break;</span><br><span style="color: hsl(0, 100%, 40%);">-          }</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%);">-                bsc_dtap(conn, link_id, msg);</span><br><span style="color: hsl(0, 100%, 40%);">-           break;</span><br><span style="color: hsl(0, 100%, 40%);">-  }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief RSL has received a DATA INDICATION with L3 from MS */</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        int rc;</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm_lchan *lchan;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        lchan = msg->lchan;</span><br><span style="color: hsl(0, 100%, 40%);">-  if (lchan->state != LCHAN_S_ACTIVE) {</span><br><span style="color: hsl(0, 100%, 40%);">-                LOGPLCHAN(msg->lchan, DRSL, LOGL_INFO, "Got data in non active state, discarding.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-             return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (lchan->conn) {</span><br><span style="color: hsl(0, 100%, 40%);">-           /* if we already have a connection, forward via DTAP to</span><br><span style="color: hsl(0, 100%, 40%);">-          * MSC */</span><br><span style="color: hsl(0, 100%, 40%);">-               dispatch_dtap(lchan->conn, link_id, msg);</span><br><span style="color: hsl(0, 100%, 40%);">-    } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                /* allocate a new connection */</span><br><span style="color: hsl(0, 100%, 40%);">-         rc = BSC_API_CONN_POL_REJECT;</span><br><span style="color: hsl(0, 100%, 40%);">-           lchan->conn = bsc_subscr_con_allocate(msg->lchan->ts->trx->bts->network);</span><br><span style="color: hsl(0, 100%, 40%);">-             if (!lchan->conn) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  lchan_release(lchan, 1, RSL_REL_NORMAL);</span><br><span style="color: hsl(0, 100%, 40%);">-                        return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(0, 100%, 40%);">-               lchan->conn->lchan = lchan;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               /* fwd via bsc_api to send COMPLETE L3 INFO to MSC */</span><br><span style="color: hsl(0, 100%, 40%);">-           rc = bsc_compl_l3(lchan->conn, msg, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-              if (rc != BSC_API_CONN_POL_ACCEPT) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    //osmo_fsm_inst_dispatch(lchan->conn->fi, FIXME, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-           }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /*! \brief We received a GSM 08.08 CIPHER MODE from the MSC */</span><br><span> int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,</span><br><span>                  const uint8_t *key, int len, int include_imeisv)</span><br><span>diff --git a/src/osmo-bsc/gsm_04_08_rr.c b/src/osmo-bsc/gsm_04_08_rr.c</span><br><span>index 64eace7..e6b654a 100644</span><br><span>--- a/src/osmo-bsc/gsm_04_08_rr.c</span><br><span>+++ b/src/osmo-bsc/gsm_04_08_rr.c</span><br><span>@@ -36,6 +36,8 @@</span><br><span> #include <osmocom/bsc/signal.h></span><br><span> #include <osmocom/bsc/bsc_subscr_conn_fsm.h></span><br><span> #include <osmocom/bsc/gsm_04_08_rr.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bsc/chan_alloc.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bsc/bsc_api.h></span><br><span> </span><br><span> /* should ip.access BTS use direct RTP streams between each other (1),</span><br><span>  * or should OpenBSC always act as RTP relay/proxy in between (0) ? */</span><br><span>@@ -716,3 +718,308 @@</span><br><span> </span><br><span>   return ret;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void handle_ass_compl(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(120, 100%, 40%);">+                           struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+  enum gsm48_rr_cause cause;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Expecting gsm48_hdr + cause value */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (msgb_l3len(msg) != sizeof(*gh) + 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+             LOGPLCHAN(msg->lchan, DRR, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                       "RR Assignment Complete: length invalid: %u, expected %zu\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                       msgb_l3len(msg), sizeof(*gh) + 1);</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   cause = gh->data[0];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG, "ASSIGNMENT COMPLETE cause = %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                 rr_cause_name(cause));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (conn->ho) {</span><br><span style="color: hsl(120, 100%, 40%);">+            struct lchan_signal_data sig = {</span><br><span style="color: hsl(120, 100%, 40%);">+                      .lchan = msg->lchan,</span><br><span style="color: hsl(120, 100%, 40%);">+               };</span><br><span style="color: hsl(120, 100%, 40%);">+            osmo_signal_dispatch(SS_LCHAN, S_LCHAN_ASSIGNMENT_COMPL, &sig);</span><br><span style="color: hsl(120, 100%, 40%);">+           /* FIXME: release old channel */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            /* send pending messages, if any */</span><br><span style="color: hsl(120, 100%, 40%);">+           gscon_dtap_queue_flush(conn, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (conn->secondary_lchan != msg->lchan) {</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGPLCHAN(msg->lchan, DRR, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                       "RR Assignment Complete does not match conn's secondary lchan.\n");</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   lchan_release(conn->lchan, 0, RSL_REL_LOCAL_END);</span><br><span style="color: hsl(120, 100%, 40%);">+  conn->lchan = conn->secondary_lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+    conn->secondary_lchan = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* send pending messages, if any */</span><br><span style="color: hsl(120, 100%, 40%);">+   gscon_dtap_queue_flush(conn, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (is_ipaccess_bts(conn_get_bts(conn)) && conn->lchan->tch_mode != GSM48_CMODE_SIGN)</span><br><span style="color: hsl(120, 100%, 40%);">+           rsl_ipacc_crcx(conn->lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_assign_compl(conn, cause);</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 handle_ass_fail(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(120, 100%, 40%);">+                          struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t *rr_failure;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct gsm48_hdr *gh;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (conn->ho) {</span><br><span style="color: hsl(120, 100%, 40%);">+            struct lchan_signal_data sig;</span><br><span style="color: hsl(120, 100%, 40%);">+         struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG, "ASSIGNMENT FAILED cause = %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                   rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           sig.lchan = msg->lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+            sig.mr = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                osmo_signal_dispatch(SS_LCHAN, S_LCHAN_ASSIGNMENT_FAIL, &sig);</span><br><span style="color: hsl(120, 100%, 40%);">+            /* FIXME: release allocated new channel */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          /* send pending messages, if any */</span><br><span style="color: hsl(120, 100%, 40%);">+           gscon_dtap_queue_flush(conn, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (conn->lchan != msg->lchan) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGPLCHAN(msg->lchan, DMSC, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                      "Assignment failure should occur on primary lchan.\n");</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* stop the timer and release it */</span><br><span style="color: hsl(120, 100%, 40%);">+   if (conn->secondary_lchan) {</span><br><span style="color: hsl(120, 100%, 40%);">+               lchan_release(conn->secondary_lchan, 0, RSL_REL_LOCAL_END);</span><br><span style="color: hsl(120, 100%, 40%);">+                conn->secondary_lchan = 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%);">+   /* send pending messages, if any */</span><br><span style="color: hsl(120, 100%, 40%);">+   gscon_dtap_queue_flush(conn, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (msgb_l3len(msg) - sizeof(*gh) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+             LOGPLCHAN(conn->lchan, DMSC, LOGL_ERROR, "assignment failure unhandled: %zu\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                    msgb_l3len(msg) - sizeof(*gh));</span><br><span style="color: hsl(120, 100%, 40%);">+             rr_failure = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              rr_failure = &gh->data[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%);">+   bsc_assign_fail(conn, GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, rr_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%);">+static void handle_classmark_chg(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(120, 100%, 40%);">+                               struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t cm2_len, cm3_len = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *cm2, *cm3 = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG, "CLASSMARK CHANGE ");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* classmark 2 */</span><br><span style="color: hsl(120, 100%, 40%);">+     cm2_len = gh->data[0];</span><br><span style="color: hsl(120, 100%, 40%);">+     cm2 = &gh->data[1];</span><br><span style="color: hsl(120, 100%, 40%);">+    DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (payload_len > cm2_len + 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+           /* we must have a classmark3 */</span><br><span style="color: hsl(120, 100%, 40%);">+               if (gh->data[cm2_len+1] != 0x20) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 DEBUGPC(DRR, "ERR CM3 TAG\n");</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%);">+             if (cm2_len > 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 DEBUGPC(DRR, "CM2 too long!\n");</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           cm3_len = gh->data[cm2_len+2];</span><br><span style="color: hsl(120, 100%, 40%);">+             cm3 = &gh->data[cm2_len+3];</span><br><span style="color: hsl(120, 100%, 40%);">+            if (cm3_len > 14) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);</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%);">+             DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     bsc_cm_update(conn, cm2, cm2_len, cm3, cm3_len);</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%);">+/* Chapter 9.1.16 Handover complete */</span><br><span style="color: hsl(120, 100%, 40%);">+static void handle_rr_ho_compl(struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct lchan_signal_data sig;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+               "HANDOVER COMPLETE cause = %s\n", rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       sig.lchan = msg->lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+    sig.mr = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_COMPL, &sig);</span><br><span style="color: hsl(120, 100%, 40%);">+     /* FIXME: release old channel */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* send pending messages, if any */</span><br><span style="color: hsl(120, 100%, 40%);">+   gscon_dtap_queue_flush(msg->lchan->conn, 1);</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%);">+/* Chapter 9.1.17 Handover Failure */</span><br><span style="color: hsl(120, 100%, 40%);">+static void handle_rr_ho_fail(struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct lchan_signal_data sig;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Log on both RR and HO categories: it is an RR message, but is still quite important when</span><br><span style="color: hsl(120, 100%, 40%);">+    * filtering on HO. */</span><br><span style="color: hsl(120, 100%, 40%);">+        LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+               "HANDOVER FAILED cause = %s\n", rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(120, 100%, 40%);">+   LOGPLCHAN(msg->lchan, DHO, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+               "HANDOVER FAILED cause = %s\n", rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ sig.lchan = msg->lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+    sig.mr = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_FAIL, &sig);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* FIXME: release allocated new channel */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* send pending messages, if any */</span><br><span style="color: hsl(120, 100%, 40%);">+   gscon_dtap_queue_flush(msg->lchan->conn, 1);</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 dispatch_dtap(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(120, 100%, 40%);">+                      uint8_t link_id, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct gsm48_hdr *gh;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t pdisc;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t msg_type;</span><br><span style="color: hsl(120, 100%, 40%);">+     int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (msgb_l3len(msg) < sizeof(*gh)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               LOGP(DMSC, LOGL_ERROR, "(%s) Message too short for a GSM48 header.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                   bsc_subscr_name(conn->bsub));</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+    pdisc = gsm48_hdr_pdisc(gh);</span><br><span style="color: hsl(120, 100%, 40%);">+  msg_type = gsm48_hdr_msg_type(gh);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* the idea is to handle all RR messages here, and only hand</span><br><span style="color: hsl(120, 100%, 40%);">+   * MM/CC/SMS-CP/LCS up to the MSC.  Some messages like PAGING</span><br><span style="color: hsl(120, 100%, 40%);">+  * RESPONSE or CM SERVICE REQUEST will not be covered here, as</span><br><span style="color: hsl(120, 100%, 40%);">+         * they are only possible in the first L3 message of each L2</span><br><span style="color: hsl(120, 100%, 40%);">+   * channel, i.e. 'conn' will not exist and gsm0408_rcvmsg()</span><br><span style="color: hsl(120, 100%, 40%);">+    * will call api->compl_l3() for it */</span><br><span style="color: hsl(120, 100%, 40%);">+     switch (pdisc) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case GSM48_PDISC_RR:</span><br><span style="color: hsl(120, 100%, 40%);">+          switch (msg_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+           case GSM48_MT_RR_GPRS_SUSP_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+                       LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+                               "%s\n", gsm48_rr_msg_name(GSM48_MT_RR_GPRS_SUSP_REQ));</span><br><span style="color: hsl(120, 100%, 40%);">+                    break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case GSM48_MT_RR_STATUS:</span><br><span style="color: hsl(120, 100%, 40%);">+                      LOGPLCHAN(msg->lchan, DRR, LOGL_NOTICE,</span><br><span style="color: hsl(120, 100%, 40%);">+                              "%s (cause: %s)\n", gsm48_rr_msg_name(GSM48_MT_RR_STATUS),</span><br><span style="color: hsl(120, 100%, 40%);">+                                  rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(120, 100%, 40%);">+                     break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case GSM48_MT_RR_MEAS_REP:</span><br><span style="color: hsl(120, 100%, 40%);">+                    /* This shouldn't actually end up here, as RSL treats</span><br><span style="color: hsl(120, 100%, 40%);">+                     * L3 Info of 08.58 MEASUREMENT REPORT different by calling</span><br><span style="color: hsl(120, 100%, 40%);">+                    * directly into gsm48_parse_meas_rep */</span><br><span style="color: hsl(120, 100%, 40%);">+                       LOGPLCHAN(msg->lchan, DMEAS, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                             "DIRECT GSM48 MEASUREMENT REPORT ?!?\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                 gsm48_tx_rr_status(conn, GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT);</span><br><span style="color: hsl(120, 100%, 40%);">+                   break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case GSM48_MT_RR_HANDO_COMPL:</span><br><span style="color: hsl(120, 100%, 40%);">+                 handle_rr_ho_compl(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case GSM48_MT_RR_HANDO_FAIL:</span><br><span style="color: hsl(120, 100%, 40%);">+                  handle_rr_ho_fail(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+                       break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case GSM48_MT_RR_CIPH_M_COMPL:</span><br><span style="color: hsl(120, 100%, 40%);">+                        bsc_cipher_mode_compl(conn, msg, conn->lchan->encr.alg_id);</span><br><span style="color: hsl(120, 100%, 40%);">+                     break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case GSM48_MT_RR_ASS_COMPL:</span><br><span style="color: hsl(120, 100%, 40%);">+                   handle_ass_compl(conn, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+                  break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case GSM48_MT_RR_ASS_FAIL:</span><br><span style="color: hsl(120, 100%, 40%);">+                    handle_ass_fail(conn, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+                   break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:</span><br><span style="color: hsl(120, 100%, 40%);">+                 rc = gsm48_rx_rr_modif_ack(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (rc < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                                bsc_assign_fail(conn, GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+                       else</span><br><span style="color: hsl(120, 100%, 40%);">+                          bsc_assign_compl(conn, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                    break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case GSM48_MT_RR_CLSM_CHG:</span><br><span style="color: hsl(120, 100%, 40%);">+                    handle_classmark_chg(conn, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case GSM48_MT_RR_APP_INFO:</span><br><span style="color: hsl(120, 100%, 40%);">+                    /* Passing RR APP INFO to MSC, not quite</span><br><span style="color: hsl(120, 100%, 40%);">+                       * according to spec */</span><br><span style="color: hsl(120, 100%, 40%);">+                       bsc_dtap(conn, link_id, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+                 break;</span><br><span style="color: hsl(120, 100%, 40%);">+                default:</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* Drop unknown RR message */</span><br><span style="color: hsl(120, 100%, 40%);">+                 LOGPLCHAN(msg->lchan, DRR, LOGL_NOTICE,</span><br><span style="color: hsl(120, 100%, 40%);">+                              "Dropping %s 04.08 RR message\n", gsm48_rr_msg_name(msg_type));</span><br><span style="color: hsl(120, 100%, 40%);">+                   gsm48_tx_rr_status(conn, GSM48_RR_CAUSE_MSG_TYPE_N);</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%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              bsc_dtap(conn, link_id, msg);</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%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief RSL has received a DATA INDICATION with L3 from MS */</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct gsm_lchan *lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    lchan = msg->lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+        if (lchan->state != LCHAN_S_ACTIVE) {</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGPLCHAN(msg->lchan, DRSL, LOGL_INFO, "Got data in non active state, discarding.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+           return -1;</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%);">+ if (lchan->conn) {</span><br><span style="color: hsl(120, 100%, 40%);">+         /* if we already have a connection, forward via DTAP to</span><br><span style="color: hsl(120, 100%, 40%);">+                * MSC */</span><br><span style="color: hsl(120, 100%, 40%);">+             dispatch_dtap(lchan->conn, link_id, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* allocate a new connection */</span><br><span style="color: hsl(120, 100%, 40%);">+               rc = BSC_API_CONN_POL_REJECT;</span><br><span style="color: hsl(120, 100%, 40%);">+         lchan->conn = bsc_subscr_con_allocate(msg->lchan->ts->trx->bts->network);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!lchan->conn) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        lchan_release(lchan, 1, RSL_REL_NORMAL);</span><br><span style="color: hsl(120, 100%, 40%);">+                      return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+             lchan->conn->lchan = lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* fwd via bsc_api to send COMPLETE L3 INFO to MSC */</span><br><span style="color: hsl(120, 100%, 40%);">+         rc = bsc_compl_l3(lchan->conn, msg, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          if (rc != BSC_API_CONN_POL_ACCEPT) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  //osmo_fsm_inst_dispatch(lchan->conn->fi, FIXME, 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/9669">change 9669</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/9669"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-bsc </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: Ie8ee334145bf7bc3a601d395ea7ab9b2009b61c7 </div>
<div style="display:none"> Gerrit-Change-Number: 9669 </div>
<div style="display:none"> Gerrit-PatchSet: 17 </div>
<div style="display:none"> Gerrit-Owner: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>