Hello Jenkins Builder,

I'd like you to reexamine a change.  Please visit

    https://gerrit.osmocom.org/3345

to look at the new patch set (#2).

mscsplit: various preparations to separate MSC from BSC

Disable large parts of the code that depend on BSC presence. The code sections
disabled by #if BEFORE_MSCSPLIT shall be modified or dropped in the course of
adding the A-interface.

Don't set msg->lchan nor msg->dst.
Don't use lchan in libmsc.
Decouple lac from bts.

Prepare entry/exit point for MSC -> BSC and MSC -> RNC communication:
Add msc_ifaces.[hc], a_iface.c, with a general msc_tx_dtap() to redirect to
different interfaces depending on the actual subscriber connection.
While iu_tx() is going to be functional fairly soon, the a_tx() is going to be
just a dummy for some time (see comment).
Add Iu specific fields in gsm_subscriber_connection: the UE connection pointer
and an indicator for the Integrity Protection status on Iu (to be fully
implemented in later commits).
Add lac member to gsm_subscriber_connection, to allow decoupling from
bts->location_area_code. The conn->lac will actually be set in iu.c in an
upcoming commit ("add iucs.[hc]").

move to libcommon-cs: gsm48_extract_mi(), gsm48_paging_extract_mi().

libmsc: duplicate gsm0808 / gsm48 functions (towards BSC).
In osmo-nitb, libmsc would directly call the functions on the BSC level, not
always via the bsc_api. When separating libmsc from libbsc, some functions are
missing from the linkage.
Hence duplicate these functions to libmsc, add an msc_ prefix for clarity, also
add a _tx to gsm0808_cipher_mode():
* add msc_gsm0808_tx_cipher_mode() (dummy/stub)
* add msc_gsm48_tx_mm_serv_ack()
* add msc_gsm48_tx_mm_serv_rej()
Call these from libmsc instead of
* gsm0808_cipher_mode()
* gsm48_tx_mm_serv_ack()
* gsm48_tx_mm_serv_rej()
Also add a comment related to msc_gsm0808_tx_cipher_mode() in two places.

Remove internal RTP streaming code; OsmoNITB supported that, but for OsmoMSC,
this will be done with an external MGCP gateway.

Remove LCHAN_MODIFY from internal MNCC state machine.

Temporarily disable all paging to be able to link libmsc without libbsc.
Skip the paging part of channel_test because the paging is now disabled.
Employ fake paging shims in order for msc_vlr_tests to still work.

msc_compl_l3(): publish in .h, tweak return value.  Use new libmsc enum values
for return val, to avoid dependency on libbsc headers.  Make callable from
other scopes: publish in osmo_msc.h and remove 'static' in osmo_msc.c

add gsm_encr to subscr_conn
move subscr_request to gsm_subscriber.h
subscr_request_channel() -> subscr_request_conn()
move to libmsc: osmo_stats_vty_add_cmds()
gsm_04_08: remove apply_codec_restrictions()
gsm0408_test: use NULL for root ctx
move to libbsc: gsm_bts_neighbor()
move to libbsc: lchan_next_meas_rep()
move vty config for t3212 to network level (periodic lu)
remove unneccessary linking from some tests
remove handle_abisip_signal()
abis_rsl.c: don't use libvlr from libbsc

gsm_subscriber_connection: put the LAC here, so that it is available without
accessing conn->bts. In bsc_api.c, place this lac in conn for the sake of
transition: Iu and A will use this new field to pass the LAC around, but in a
completely separate OsmoBSC this is not actually needed. It can be removed
again from osmo-bsc.git when the time has come.

Siemens MRPCI: completely drop sending the MRPCI messages for now, they shall
be added in osmo-bsc once the A-Interface code has settled. See OS#2389.

Related: OS#1845 OS#2257 OS#2389
Change-Id: Id3705236350d5f69e447046b0a764bbabc3d493c
---
M include/openbsc/Makefile.am
M include/openbsc/gsm_04_08.h
M include/openbsc/gsm_data.h
M include/openbsc/gsm_subscriber.h
M include/openbsc/mncc.h
A include/openbsc/msc_ifaces.h
M include/openbsc/osmo_msc.h
M src/libbsc/abis_rsl.c
M src/libbsc/bsc_api.c
M src/libbsc/bsc_vty.c
M src/libbsc/gsm_04_08_utils.c
M src/libbsc/handover_decision.c
M src/libcommon-cs/common_cs.c
M src/libcommon-cs/common_cs_vty.c
M src/libcommon/gsm_data.c
M src/libcommon/talloc_ctx.c
M src/libmsc/Makefile.am
A src/libmsc/a_iface.c
M src/libmsc/gsm_04_08.c
M src/libmsc/gsm_04_11.c
M src/libmsc/gsm_subscriber.c
M src/libmsc/mncc_builtin.c
M src/libmsc/mncc_sock.c
A src/libmsc/msc_ifaces.c
M src/libmsc/osmo_msc.c
M src/libmsc/silent_call.c
M src/libmsc/smpp_openbsc.c
M src/libmsc/vty_interface_layer3.c
M tests/bsc/Makefile.am
M tests/channel/Makefile.am
M tests/db/Makefile.am
M tests/gsm0408/gsm0408_test.c
M tests/msc_vlr/Makefile.am
M tests/msc_vlr/msc_vlr_test_gsm_authen.err
M tests/msc_vlr/msc_vlr_test_gsm_ciph.err
M tests/msc_vlr/msc_vlr_test_no_authen.err
M tests/msc_vlr/msc_vlr_test_reject_concurrency.err
M tests/msc_vlr/msc_vlr_test_umts_authen.err
M tests/msc_vlr/msc_vlr_tests.c
39 files changed, 470 insertions(+), 1,071 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-msc refs/changes/45/3345/2

diff --git a/include/openbsc/Makefile.am b/include/openbsc/Makefile.am
index 456a4a2..1dfe6c3 100644
--- a/include/openbsc/Makefile.am
+++ b/include/openbsc/Makefile.am
@@ -54,6 +54,7 @@
        misdn.h \
        mncc.h \
        mncc_int.h \
+       msc_ifaces.h \
        nat_rewrite_trie.h \
        network_listen.h \
        oap_client.h \
diff --git a/include/openbsc/gsm_04_08.h b/include/openbsc/gsm_04_08.h
index c40d96d..6d6ead1 100644
--- a/include/openbsc/gsm_04_08.h
+++ b/include/openbsc/gsm_04_08.h
@@ -65,8 +65,6 @@
 int send_siemens_mrpci(struct gsm_lchan *lchan, uint8_t *classmark2_lv);
 int gsm48_extract_mi(uint8_t *classmark2, int length, char *mi_string, uint8_t 
*mi_type);
 int gsm48_paging_extract_mi(struct gsm48_pag_resp *pag, int length, char 
*mi_string, uint8_t *mi_type);
-int gsm48_handle_paging_resp(struct gsm_subscriber_connection *conn,
-                            struct msgb *msg, struct bsc_subscr *bsub);
 
 int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t lchan_mode);
 int gsm48_rx_rr_modif_ack(struct msgb *msg);
diff --git a/include/openbsc/gsm_data.h b/include/openbsc/gsm_data.h
index fa2fed7..17b3d71 100644
--- a/include/openbsc/gsm_data.h
+++ b/include/openbsc/gsm_data.h
@@ -26,6 +26,7 @@
 struct bsc_subscr;
 struct vlr_instance;
 struct vlr_subscr;
+struct ue_conn_ctx;
 
 #define OBSC_LINKID_CB(__msgb) (__msgb)->cb[3]
 
@@ -117,6 +118,12 @@
        uint8_t classmark3[14]; /* if cm3 gets extended by spec, it will be 
truncated */
 };
 
+enum integrity_protection_state {
+       INTEGRITY_PROTECTION_NONE       = 0,
+       INTEGRITY_PROTECTION_IK         = 1,
+       INTEGRITY_PROTECTION_IK_CK      = 2,
+};
+
 /* active radio connection of a mobile subscriber */
 struct gsm_subscriber_connection {
        /* global linked list of subscriber_connections */
@@ -176,6 +183,15 @@
        enum ran_type via_ran;
 
        struct gsm_classmark classmark;
+
+       uint16_t lac;
+       struct gsm_encr encr;
+
+       /* which Iu-CS connection, if any. */
+       struct {
+               struct ue_conn_ctx *ue_ctx;
+               int integrity_protection;
+       } iu;
 };
 
 
@@ -311,6 +327,12 @@
 };
 
 struct gsm_network {
+       /* TODO MSCSPLIT the gsm_network struct is basically a kitchen sink for
+        * global settings and variables, "madly" mixing BSC and MSC stuff. 
Split
+        * this in e.g. struct osmo_bsc and struct osmo_msc, with the things
+        * these have in common, like country and network code, put in yet
+        * separate structs and placed as members in osmo_bsc and osmo_msc. */
+
        /* global parameters */
        uint16_t country_code;
        uint16_t network_code;
@@ -416,6 +438,9 @@
        uint16_t gsup_server_port;
 
        struct vlr_instance *vlr;
+
+       /* Periodic location update default value */
+       uint8_t t3212;
 };
 
 struct osmo_esme;
@@ -470,10 +495,6 @@
 extern void talloc_ctx_init(void *ctx_root);
 
 int gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type);
-
-/* Get reference to a neighbor cell on a given BCCH ARFCN */
-struct gsm_bts *gsm_bts_neighbor(const struct gsm_bts *bts,
-                                uint16_t arfcn, uint8_t bsic);
 
 enum gsm_bts_type parse_btstype(const char *arg);
 const char *btstype2str(enum gsm_bts_type type);
@@ -557,7 +578,6 @@
 
 int gsm48_ra_id_by_bts(uint8_t *buf, struct gsm_bts *bts);
 void gprs_ra_id_by_bts(struct gprs_ra_id *raid, struct gsm_bts *bts);
-struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan);
 
 int gsm_btsmodel_set_feature(struct gsm_bts_model *model, enum 
gsm_bts_features feat);
 int gsm_bts_model_register(struct gsm_bts_model *model);
diff --git a/include/openbsc/gsm_subscriber.h b/include/openbsc/gsm_subscriber.h
index c65b8a3..60eb0cd 100644
--- a/include/openbsc/gsm_subscriber.h
+++ b/include/openbsc/gsm_subscriber.h
@@ -19,8 +19,6 @@
 
 #define GSM_SUBSCRIBER_NO_EXPIRATION   0x0
 
-struct subscr_request;
-
 enum gsm_subscriber_field {
        GSM_SUBSCRIBER_IMSI,
        GSM_SUBSCRIBER_TMSI,
@@ -34,17 +32,35 @@
        GSM_SUBSCRIBER_UPDATE_EQUIPMENT,
 };
 
-int subscr_update(struct vlr_subscr *vsub, struct gsm_bts *bts, int reason);
+/*
+ * Struct for pending channel requests. This is managed in the
+ * llist_head requests of each subscriber. The reference counting
+ * should work in such a way that a subscriber with a pending request
+ * remains in memory.
+ */
+struct subscr_request {
+       struct llist_head entry;
+
+       /* the callback data */
+       gsm_cbfn *cbfn;
+       void *param;
+};
+
+int subscr_update(struct vlr_subscr *vsub, int reason);
 
 /*
  * Paging handling with authentication
  */
-struct subscr_request *subscr_request_channel(struct vlr_subscr *vsub,
-                                             int channel_type,
-                                             gsm_cbfn *cbfn, void *param);
+struct subscr_request *subscr_request_conn(struct vlr_subscr *vsub,
+                                          int channel_type,
+                                          gsm_cbfn *cbfn, void *param);
+
 void subscr_remove_request(struct subscr_request *req);
 
 int subscr_paging_dispatch(unsigned int hooknum, unsigned int event,
                           struct msgb *msg, void *data, void *param);
 
+int msc_fake_paging_request(struct vlr_subscr *vsub);
+void msc_fake_paging_request_stop(struct vlr_subscr *vsub);
+
 #endif /* _GSM_SUBSCR_H */
diff --git a/include/openbsc/mncc.h b/include/openbsc/mncc.h
index 49f0c8b..881e041 100644
--- a/include/openbsc/mncc.h
+++ b/include/openbsc/mncc.h
@@ -155,9 +155,6 @@
        int             notify; /* 0..127 */
        int             emergency;
        char            imsi[16];
-
-       unsigned char   lchan_type;
-       unsigned char   lchan_mode;
 };
 
 struct gsm_data_frame {
@@ -179,7 +176,6 @@
        uint32_t        called_offset;
        uint32_t        signal_offset;
        uint32_t        emergency_offset;
-       uint32_t        lchan_type_offset;
 };
 
 struct gsm_mncc_rtp {
diff --git a/include/openbsc/msc_ifaces.h b/include/openbsc/msc_ifaces.h
new file mode 100644
index 0000000..83aad92
--- /dev/null
+++ b/include/openbsc/msc_ifaces.h
@@ -0,0 +1,47 @@
+#pragma once
+
+#include <osmocom/core/msgb.h>
+#include <openbsc/gsm_data.h>
+
+/* These are the interfaces of the MSC layer towards (from?) the BSC and RNC,
+ * i.e. in the direction towards the mobile device (MS aka UE).
+ *
+ * 2G will use the A-interface,
+ * 3G aka UMTS will use the Iu-interface (for the MSC, it's IuCS).
+ *
+ * To allow linking parts of the MSC code without having to include entire
+ * infrastructures of external libraries, the core transmitting and receiving
+ * functions are left unimplemented. For example, a unit test does not need to
+ * link against external ASN1 libraries if it is never going to encode actual
+ * outgoing messages. It is up to each building scope to implement real world
+ * functions or to plug mere dummy implementations.
+ *
+ * For example, msc_tx_dtap(conn, msg), depending on conn->via_iface, will call
+ * either iu_tx() or a_tx() [note: at time of writing, the A-interface is not
+ * yet implemented]. When you try to link against libmsc, you will find that
+ * the compiler complains about an undefined reference to iu_tx(). If you,
+ * however, link against libiu as well as the osmo-iuh libs (etc.), iu_tx() is
+ * available. A unit test may instead simply implement a dummy iu_tx() function
+ * and not link against osmo-iuh.
+ */
+
+/* Each main linkage must implement this function (see comment above). */
+extern int iu_tx(struct msgb *msg, uint8_t sapi);
+
+/* So far this is a dummy implemented in libmsc/a_iface.c. When A-interface
+ * gets implemented, it should be in a separate lib (like libiu), this function
+ * should move there, and the following comment should remain here: "
+ * Each main linkage must implement this function (see comment above).
+ * " */
+extern int a_tx(struct msgb *msg);
+
+int msc_tx_dtap(struct gsm_subscriber_connection *conn,
+               struct msgb *msg);
+
+int msc_gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn);
+int msc_gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
+                            enum gsm48_reject_value value);
+
+/* TODO: specific to A interface, move this away */
+int msc_gsm0808_tx_cipher_mode(struct gsm_subscriber_connection *conn, int 
cipher,
+                              const uint8_t *key, int len, int include_imeisv);
diff --git a/include/openbsc/osmo_msc.h b/include/openbsc/osmo_msc.h
index 0642c91..5a26b60 100644
--- a/include/openbsc/osmo_msc.h
+++ b/include/openbsc/osmo_msc.h
@@ -51,6 +51,11 @@
        return get_value_string(subscr_conn_from_names, val);
 }
 
+enum msc_compl_l3_rc {
+       MSC_CONN_ACCEPT = 0,
+       MSC_CONN_REJECT = 1,
+};
+
 
 struct bsc_api *msc_bsc_api();
 
diff --git a/src/libbsc/abis_rsl.c b/src/libbsc/abis_rsl.c
index 7ae3eeb..441b386 100644
--- a/src/libbsc/abis_rsl.c
+++ b/src/libbsc/abis_rsl.c
@@ -1423,6 +1423,19 @@
        }
 }
 
+static struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan)
+{
+       struct gsm_meas_rep *meas_rep;
+
+       meas_rep = &lchan->meas_rep[lchan->meas_rep_idx];
+       memset(meas_rep, 0, sizeof(*meas_rep));
+       meas_rep->lchan = lchan;
+       lchan->meas_rep_idx = (lchan->meas_rep_idx + 1)
+                                       % ARRAY_SIZE(lchan->meas_rep);
+
+       return meas_rep;
+}
+
 static int rsl_rx_meas_res(struct msgb *msg)
 {
        struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
diff --git a/src/libbsc/bsc_api.c b/src/libbsc/bsc_api.c
index 947644e..c2828e3 100644
--- a/src/libbsc/bsc_api.c
+++ b/src/libbsc/bsc_api.c
@@ -264,6 +264,7 @@
        conn->lchan = lchan;
        conn->bts = lchan->ts->trx->bts;
        conn->via_ran = RAN_GERAN_A;
+       conn->lac = conn->bts->location_area_code;
        lchan->conn = conn;
        llist_add_tail(&conn->entry, &net->subscr_conns);
        return conn;
diff --git a/src/libbsc/bsc_vty.c b/src/libbsc/bsc_vty.c
index 3bd56ea..722753a 100644
--- a/src/libbsc/bsc_vty.c
+++ b/src/libbsc/bsc_vty.c
@@ -593,18 +593,12 @@
                                (sp->penalty_time*20)+20, VTY_NEWLINE);
        }
 
-       /* Is periodic LU enabled or disabled? */
-       if (bts->si_common.chan_desc.t3212 == 0)
-               vty_out(vty, "  no periodic location update%s", VTY_NEWLINE);
-       else
-               vty_out(vty, "  periodic location update %u%s",
-                       bts->si_common.chan_desc.t3212 * 6, VTY_NEWLINE);
-
        if (gsm_bts_get_radio_link_timeout(bts) < 0)
                vty_out(vty, "  radio-link-timeout infinite%s", VTY_NEWLINE);
        else
                vty_out(vty, "  radio-link-timeout %d%s",
                        gsm_bts_get_radio_link_timeout(bts), VTY_NEWLINE);
+       
        vty_out(vty, "  channel allocator %s%s",
                bts->chan_alloc_reverse ? "descending" : "ascending",
                VTY_NEWLINE);
@@ -841,6 +835,11 @@
                        vty_out(vty, " timezone %d %d%s",
                                gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
        }
+       if (gsmnet->t3212 == 0)
+               vty_out(vty, " no periodic location update%s", VTY_NEWLINE);
+       else
+               vty_out(vty, " periodic location update %u%s",
+                       gsmnet->t3212 * 6, VTY_NEWLINE);
 
        return CMD_SUCCESS;
 }
@@ -2262,34 +2261,6 @@
 
        bts->si_common.cell_ro_sel_par.present = 1;
        bts->si_common.cell_ro_sel_par.penalty_time = 31;
-
-       return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_per_loc_upd, cfg_bts_per_loc_upd_cmd,
-      "periodic location update <6-1530>",
-      "Periodic Location Updating Interval\n"
-      "Periodic Location Updating Interval\n"
-      "Periodic Location Updating Interval\n"
-      "Periodic Location Updating Interval in Minutes\n")
-{
-       struct gsm_bts *bts = vty->index;
-
-       bts->si_common.chan_desc.t3212 = atoi(argv[0]) / 6;
-
-       return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_no_per_loc_upd, cfg_bts_no_per_loc_upd_cmd,
-      "no periodic location update",
-      NO_STR
-      "Periodic Location Updating Interval\n"
-      "Periodic Location Updating Interval\n"
-      "Periodic Location Updating Interval\n")
-{
-       struct gsm_bts *bts = vty->index;
-
-       bts->si_common.chan_desc.t3212 = 0;
 
        return CMD_SUCCESS;
 }
@@ -4129,7 +4100,6 @@
        install_element_ve(&show_paging_group_cmd);
 
        logging_vty_add_cmds(NULL);
-       osmo_stats_vty_add_cmds();
 
        install_element(GSMNET_NODE, &cfg_net_neci_cmd);
        install_element(GSMNET_NODE, &cfg_net_handover_cmd);
@@ -4189,8 +4159,6 @@
        install_element(BTS_NODE, &cfg_bts_rach_ec_allowed_cmd);
        install_element(BTS_NODE, &cfg_bts_rach_ac_class_cmd);
        install_element(BTS_NODE, &cfg_bts_ms_max_power_cmd);
-       install_element(BTS_NODE, &cfg_bts_per_loc_upd_cmd);
-       install_element(BTS_NODE, &cfg_bts_no_per_loc_upd_cmd);
        install_element(BTS_NODE, &cfg_bts_cell_resel_hyst_cmd);
        install_element(BTS_NODE, &cfg_bts_rxlev_acc_min_cmd);
        install_element(BTS_NODE, &cfg_bts_cell_bar_qualify_cmd);
diff --git a/src/libbsc/gsm_04_08_utils.c b/src/libbsc/gsm_04_08_utils.c
index 3447d27..7c5e0e9 100644
--- a/src/libbsc/gsm_04_08_utils.c
+++ b/src/libbsc/gsm_04_08_utils.c
@@ -270,61 +270,6 @@
        return rsl_siemens_mrpci(lchan, &mrpci);
 }
 
-int gsm48_extract_mi(uint8_t *classmark2_lv, int length, char *mi_string, 
uint8_t *mi_type)
-{
-       /* Check the size for the classmark */
-       if (length < 1 + *classmark2_lv)
-               return -1;
-
-       uint8_t *mi_lv = classmark2_lv + *classmark2_lv + 1;
-       if (length < 2 + *classmark2_lv + mi_lv[0])
-               return -2;
-
-       *mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
-       return gsm48_mi_to_string(mi_string, GSM48_MI_SIZE, mi_lv+1, *mi_lv);
-}
-
-int gsm48_paging_extract_mi(struct gsm48_pag_resp *resp, int length,
-                           char *mi_string, uint8_t *mi_type)
-{
-       static const uint32_t classmark_offset =
-               offsetof(struct gsm48_pag_resp, classmark2);
-       uint8_t *classmark2_lv = (uint8_t *) &resp->classmark2;
-       return gsm48_extract_mi(classmark2_lv, length - classmark_offset,
-                               mi_string, mi_type);
-}
-
-int gsm48_handle_paging_resp(struct gsm_subscriber_connection *conn,
-                            struct msgb *msg, struct bsc_subscr *bsub)
-{
-       struct gsm_bts *bts = msg->lchan->ts->trx->bts;
-       struct gsm48_hdr *gh = msgb_l3(msg);
-       uint8_t *classmark2_lv = gh->data + 1;
-
-       if (is_siemens_bts(bts))
-               send_siemens_mrpci(msg->lchan, classmark2_lv);
-
-       if (!conn->bsub) {
-               conn->bsub = bsub;
-       } else if (conn->bsub != bsub) {
-               LOGP(DRR, LOGL_ERROR,
-                    "<- Channel already owned by someone else?\n");
-               bsc_subscr_put(bsub);
-               return -EINVAL;
-       } else {
-               DEBUGP(DRR, "<- Channel already owned by us\n");
-               bsc_subscr_put(bsub);
-               bsub = conn->bsub;
-       }
-
-       rate_ctr_inc(&bts->network->bsc_ctrs->ctr[BSC_CTR_PAGING_COMPLETED]);
-
-       /* Stop paging on the bts we received the paging response */
-       paging_request_stop(&bts->network->bts_list, conn->bts, bsub, conn,
-                           msg);
-       return 0;
-}
-
 /* Chapter 9.1.9: Ciphering Mode Command */
 int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv)
 {
diff --git a/src/libbsc/handover_decision.c b/src/libbsc/handover_decision.c
index 0f07bca..8d7e047 100644
--- a/src/libbsc/handover_decision.c
+++ b/src/libbsc/handover_decision.c
@@ -33,6 +33,27 @@
 #include <openbsc/handover.h>
 #include <osmocom/gsm/gsm_utils.h>
 
+/* Get reference to a neighbor cell on a given BCCH ARFCN */
+static struct gsm_bts *gsm_bts_neighbor(const struct gsm_bts *bts,
+                                       uint16_t arfcn, uint8_t bsic)
+{
+       struct gsm_bts *neigh;
+       /* FIXME: use some better heuristics here to determine which cell
+        * using this ARFCN really is closest to the target cell.  For
+        * now we simply assume that each ARFCN will only be used by one
+        * cell */
+
+       llist_for_each_entry(neigh, &bts->network->bts_list, list) {
+               /* FIXME: this is probably returning the same bts again!? */
+               if (neigh->c0->arfcn == arfcn &&
+                   neigh->bsic == bsic)
+                       return neigh;
+       }
+
+       return NULL;
+}
+
+
 /* issue handover to a cell identified by ARFCN and BSIC */
 static int handover_to_arfcn_bsic(struct gsm_lchan *lchan,
                                  uint16_t arfcn, uint8_t bsic)
diff --git a/src/libcommon-cs/common_cs.c b/src/libcommon-cs/common_cs.c
index fc9caaf..8e19bb2 100644
--- a/src/libcommon-cs/common_cs.c
+++ b/src/libcommon-cs/common_cs.c
@@ -56,6 +56,9 @@
        net->country_code = country_code;
        net->network_code = network_code;
 
+       /* Use 30 min periodic update interval as sane default */
+       net->t3212 = 5;
+
        INIT_LLIST_HEAD(&net->trans_list);
        INIT_LLIST_HEAD(&net->upqueue);
        INIT_LLIST_HEAD(&net->subscr_conns);
@@ -107,6 +110,30 @@
        return msg;
 }
 
+int gsm48_extract_mi(uint8_t *classmark2_lv, int length, char *mi_string, 
uint8_t *mi_type)
+{
+       /* Check the size for the classmark */
+       if (length < 1 + *classmark2_lv)
+               return -1;
+
+       uint8_t *mi_lv = classmark2_lv + *classmark2_lv + 1;
+       if (length < 2 + *classmark2_lv + mi_lv[0])
+               return -2;
+
+       *mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
+       return gsm48_mi_to_string(mi_string, GSM48_MI_SIZE, mi_lv+1, *mi_lv);
+}
+
+int gsm48_paging_extract_mi(struct gsm48_pag_resp *resp, int length,
+                           char *mi_string, uint8_t *mi_type)
+{
+       static const uint32_t classmark_offset =
+               offsetof(struct gsm48_pag_resp, classmark2);
+       uint8_t *classmark2_lv = (uint8_t *) &resp->classmark2;
+       return gsm48_extract_mi(classmark2_lv, length - classmark_offset,
+                               mi_string, mi_type);
+}
+
 uint8_t sms_next_rp_msg_ref(uint8_t *next_rp_ref)
 {
        const uint8_t rp_msg_ref = *next_rp_ref;
diff --git a/src/libcommon-cs/common_cs_vty.c b/src/libcommon-cs/common_cs_vty.c
index 86b4c53..1791687 100644
--- a/src/libcommon-cs/common_cs_vty.c
+++ b/src/libcommon-cs/common_cs_vty.c
@@ -284,6 +284,34 @@
        return CMD_SUCCESS;
 }
 
+DEFUN(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
+      "periodic location update <6-1530>",
+      "Periodic Location Updating Interval\n"
+      "Periodic Location Updating Interval\n"
+      "Periodic Location Updating Interval\n"
+      "Periodic Location Updating Interval in Minutes\n")
+{
+       struct gsm_network *net = vty->index;
+
+       net->t3212 = atoi(argv[0]) / 6;
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
+      "no periodic location update",
+      NO_STR
+      "Periodic Location Updating Interval\n"
+      "Periodic Location Updating Interval\n"
+      "Periodic Location Updating Interval\n")
+{
+       struct gsm_network *net = vty->index;
+
+       net->t3212 = 0;
+
+       return CMD_SUCCESS;
+}
+
 static struct gsm_network *vty_global_gsm_network = NULL;
 
 /* initialize VTY elements used in both BSC and MSC */
@@ -292,6 +320,8 @@
 {
        OSMO_ASSERT(vty_global_gsm_network == NULL);
        vty_global_gsm_network = network;
+
+       osmo_stats_vty_add_cmds();
 
        install_element(CONFIG_NODE, &cfg_net_cmd);
        install_node(&net_node, config_write_net);
@@ -310,6 +340,8 @@
        install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
        install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
        install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
+       install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
+       install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
        install_element(GSMNET_NODE, &cfg_net_dyn_ts_allow_tch_f_cmd);
 
        return CMD_SUCCESS;
diff --git a/src/libcommon/gsm_data.c b/src/libcommon/gsm_data.c
index 7c717a4..f6fde37 100644
--- a/src/libcommon/gsm_data.c
+++ b/src/libcommon/gsm_data.c
@@ -71,25 +71,6 @@
        return 0;
 }
 
-/* Get reference to a neighbor cell on a given BCCH ARFCN */
-struct gsm_bts *gsm_bts_neighbor(const struct gsm_bts *bts,
-                                uint16_t arfcn, uint8_t bsic)
-{
-       struct gsm_bts *neigh;
-       /* FIXME: use some better heuristics here to determine which cell
-        * using this ARFCN really is closest to the target cell.  For
-        * now we simply assume that each ARFCN will only be used by one
-        * cell */
-
-       llist_for_each_entry(neigh, &bts->network->bts_list, list) {
-               if (neigh->c0->arfcn == arfcn &&
-                   neigh->bsic == bsic)
-                       return neigh;
-       }
-
-       return NULL;
-}
-
 const struct value_string bts_type_descs[_NUM_GSM_BTS_TYPE+1] = {
        { GSM_BTS_TYPE_UNKNOWN,         "Unknown BTS Type" },
        { GSM_BTS_TYPE_BS11,            "Siemens BTS (BS-11 or compatible)" },
@@ -210,19 +191,6 @@
        return 1;
 }
 
-struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan)
-{
-       struct gsm_meas_rep *meas_rep;
-
-       meas_rep = &lchan->meas_rep[lchan->meas_rep_idx];
-       memset(meas_rep, 0, sizeof(*meas_rep));
-       meas_rep->lchan = lchan;
-       lchan->meas_rep_idx = (lchan->meas_rep_idx + 1)
-                                       % ARRAY_SIZE(lchan->meas_rep);
-
-       return meas_rep;
-}
-
 int gsm_btsmodel_set_feature(struct gsm_bts_model *model, enum 
gsm_bts_features feat)
 {
        OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES);
@@ -322,7 +290,7 @@
        bts->si_common.chan_desc.att = 1; /* attachment required */
        bts->si_common.chan_desc.bs_pa_mfrms = RSL_BS_PA_MFRMS_5; /* paging 
frames */
        bts->si_common.chan_desc.bs_ag_blks_res = 1; /* reserved AGCH blocks */
-       bts->si_common.chan_desc.t3212 = 5; /* Use 30 min periodic update 
interval as sane default */
+       bts->si_common.chan_desc.t3212 = net->t3212; /* Use network's current 
value */
        gsm_bts_set_radio_link_timeout(bts, 32); /* Use RADIO LINK TIMEOUT of 
32 */
 
        llist_add_tail(&bts->list, &net->bts_list);
diff --git a/src/libcommon/talloc_ctx.c b/src/libcommon/talloc_ctx.c
index 5e3d9ae..c8e9cd3 100644
--- a/src/libcommon/talloc_ctx.c
+++ b/src/libcommon/talloc_ctx.c
@@ -44,7 +44,6 @@
        tall_authciphop_ctx = talloc_named_const(ctx_root, 0, "auth_ciph_oper");
        tall_gsms_ctx = talloc_named_const(ctx_root, 0, "sms");
        tall_subscr_ctx = talloc_named_const(ctx_root, 0, "subscriber");
-       tall_sub_req_ctx = talloc_named_const(ctx_root, 0, "subscr_request");
        tall_call_ctx = talloc_named_const(ctx_root, 0, "gsm_call");
        tall_paging_ctx = talloc_named_const(ctx_root, 0, "paging_request");
        tall_sigh_ctx = talloc_named_const(ctx_root, 0, "signal_handler");
diff --git a/src/libmsc/Makefile.am b/src/libmsc/Makefile.am
index bb2a4a1..3c06514 100644
--- a/src/libmsc/Makefile.am
+++ b/src/libmsc/Makefile.am
@@ -23,6 +23,7 @@
        $(NULL)
 
 libmsc_a_SOURCES = \
+       a_iface.c \
        auth.c \
        db.c \
        gsm_04_08.c \
@@ -32,6 +33,7 @@
        mncc.c \
        mncc_builtin.c \
        mncc_sock.c \
+       msc_ifaces.c \
        rrlp.c \
        silent_call.c \
        sms_queue.c \
diff --git a/src/libmsc/a_iface.c b/src/libmsc/a_iface.c
new file mode 100644
index 0000000..1f471f9
--- /dev/null
+++ b/src/libmsc/a_iface.c
@@ -0,0 +1,45 @@
+/* A-interface implementation, from MSC to BSC */
+
+/* (C) 2016 by sysmocom s.m.f.c GmbH <[email protected]>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/logging.h>
+
+#include <openbsc/debug.h>
+
+#include <openbsc/gsm_data.h>
+#include <openbsc/msc_ifaces.h>
+#include <openbsc/debug.h>
+
+int a_tx(struct msgb *msg)
+{
+       LOGP(DMSC, LOGL_ERROR, "message to be sent to BSC, but A-interface"
+            " not implemented.\n%s\n", osmo_hexdump(msg->data, msg->len));
+       return -1;
+}
+
+int msc_gsm0808_tx_cipher_mode(struct gsm_subscriber_connection *conn, int 
cipher,
+                              const uint8_t *key, int len, int include_imeisv)
+{
+       /* TODO generalize for A- and Iu interfaces, don't name after 08.08 */
+       LOGP(DMSC, LOGL_ERROR, "gsm0808_cipher_mode(): message to be sent to"
+            " BSC, but A interface not yet implemented.\n");
+       return -1;
+}
diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c
index 6cea242..21ffaaa 100644
--- a/src/libmsc/gsm_04_08.c
+++ b/src/libmsc/gsm_04_08.c
@@ -59,6 +59,7 @@
 #include <osmocom/abis/e1_input.h>
 #include <osmocom/core/bitvec.h>
 #include <openbsc/vlr.h>
+#include <openbsc/msc_ifaces.h>
 
 #include <osmocom/gsm/gsm48.h>
 #include <osmocom/gsm/gsm0480.h>
@@ -71,10 +72,9 @@
 
 #include <assert.h>
 
+
 void *tall_locop_ctx;
 void *tall_authciphop_ctx;
-
-static int tch_rtp_signal(struct gsm_lchan *lchan, int signal);
 
 static int gsm0408_loc_upd_acc(struct gsm_subscriber_connection *conn,
                               uint32_t send_tmsi);
@@ -86,29 +86,6 @@
        uint16_t mnc;
        uint16_t lac;
 };
-
-static int apply_codec_restrictions(struct gsm_bts *bts,
-       struct gsm_mncc_bearer_cap *bcap)
-{
-       int i, j;
-
-       /* remove unsupported speech versions from list */
-       for (i = 0, j = 0; bcap->speech_ver[i] >= 0; i++) {
-               if (bcap->speech_ver[i] == GSM48_BCAP_SV_FR)
-                       bcap->speech_ver[j++] = GSM48_BCAP_SV_FR;
-               if (bcap->speech_ver[i] == GSM48_BCAP_SV_EFR && bts->codec.efr)
-                       bcap->speech_ver[j++] = GSM48_BCAP_SV_EFR;
-               if (bcap->speech_ver[i] == GSM48_BCAP_SV_AMR_F && 
bts->codec.amr)
-                       bcap->speech_ver[j++] = GSM48_BCAP_SV_AMR_F;
-               if (bcap->speech_ver[i] == GSM48_BCAP_SV_HR && bts->codec.hr)
-                       bcap->speech_ver[j++] = GSM48_BCAP_SV_HR;
-               if (bcap->speech_ver[i] == GSM48_BCAP_SV_AMR_H && 
bts->codec.amr)
-                       bcap->speech_ver[j++] = GSM48_BCAP_SV_AMR_H;
-       }
-       bcap->speech_ver[j] = -1;
-
-       return 0;
-}
 
 static uint32_t new_callref = 0x80000001;
 
@@ -126,27 +103,6 @@
         * work that the caller no longer has to do */
        if (trans) {
                gh->proto_discr = trans->protocol | (trans->transaction_id << 
4);
-               msg->lchan = trans->conn->lchan;
-       }
-
-       if (msg->lchan) {
-               struct e1inp_sign_link *sign_link =
-                               msg->lchan->ts->trx->rsl_link;
-
-               msg->dst = sign_link;
-               if (gsm48_hdr_pdisc(gh) == GSM48_PDISC_CC)
-                       DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
-                               "Sending '%s' to MS.\n",
-                               sign_link->trx->bts->nr,
-                               sign_link->trx->nr, msg->lchan->ts->nr,
-                               gh->proto_discr & 0xf0,
-                               gsm48_cc_msg_name(gh->msg_type));
-               else
-                       DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
-                               "Sending 0x%02x to MS.\n",
-                               sign_link->trx->bts->nr,
-                               sign_link->trx->nr, msg->lchan->ts->nr,
-                               gh->proto_discr, gh->msg_type);
        }
 
        return gsm0808_submit_dtap(conn, msg, 0, 0);
@@ -187,7 +143,6 @@
 /* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
 int gsm0408_loc_upd_rej(struct gsm_subscriber_connection *conn, uint8_t cause)
 {
-       struct gsm_bts *bts = conn->bts;
        struct msgb *msg;
 
        msg = gsm48_create_loc_upd_rej(cause);
@@ -196,11 +151,8 @@
                return -1;
        }
 
-       msg->lchan = conn->lchan;
-
-       LOGP(DMM, LOGL_INFO, "Subscriber %s: LOCATION UPDATING REJECT "
-            "LAC=%u BTS=%u\n", vlr_subscr_name(conn->vsub),
-            bts->location_area_code, bts->nr);
+       LOGP(DMM, LOGL_INFO, "Subscriber %s: LOCATION UPDATING REJECT\n",
+            vlr_subscr_name(conn->vsub));
 
        return gsm48_conn_sendmsg(msg, conn, NULL);
 }
@@ -214,8 +166,6 @@
        struct gsm48_loc_area_id *lai;
        uint8_t *mid;
 
-       msg->lchan = conn->lchan;
-
        gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
        gh->proto_discr = GSM48_PDISC_MM;
        gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
@@ -223,7 +173,7 @@
        lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
        gsm48_generate_lai(lai, conn->network->country_code,
                           conn->network->network_code,
-                          conn->bts->location_area_code);
+                          conn->lac);
 
        if (send_tmsi == GSM_RESERVED_TMSI) {
                /* we did not allocate a TMSI to the MS, so we need to
@@ -257,8 +207,6 @@
 {
        struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ID REQ");
        struct gsm48_hdr *gh;
-
-       msg->lchan = conn->lchan;
 
        gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
        gh->proto_discr = GSM48_PDISC_MM;
@@ -376,7 +324,7 @@
                         &old_lai.plmn.mnc, &old_lai.lac);
        new_lai.plmn.mcc = conn->network->country_code;
        new_lai.plmn.mnc = conn->network->network_code;
-       new_lai.lac = conn->bts->location_area_code;
+       new_lai.lac = conn->lac;
        DEBUGP(DMM, "LU/new-LAC: %u/%u\n", old_lai.lac, new_lai.lac);
 
        lu_fsm = vlr_loc_update(conn->conn_fsm,
@@ -436,8 +384,6 @@
        struct tm* local_time;
        int tzunits;
        int dst = 0;
-
-       msg->lchan = conn->lchan;
 
        gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
        gh->proto_discr = GSM48_PDISC_MM;
@@ -588,7 +534,6 @@
        if (autn)
                DEBUGP(DMM, "   AUTH REQ (autn = %s)\n", 
osmo_hexdump_nospc(autn, 16));
 
-       msg->lchan = conn->lchan;
        gh->proto_discr = GSM48_PDISC_MM;
        gh->msg_type = GSM48_MT_MM_AUTH_REQ;
 
@@ -663,7 +608,7 @@
  * b) Try to parse the TMSI. If we do not have one reject
  * c) Check that we know the subscriber with the TMSI otherwise reject
  *    with a HLR cause
- * d) Set the subscriber on the gsm_lchan and accept
+ * d) Set the subscriber on the conn and accept
  *
  * Keep this function non-static for direct invocation by unit tests.
  */
@@ -688,19 +633,19 @@
 
        lai.plmn.mcc = conn->network->country_code;
        lai.plmn.mnc = conn->network->network_code;
-       lai.lac = conn->bts->location_area_code;
+       lai.lac = conn->lac;
 
        DEBUGP(DMM, "<- CM SERVICE REQUEST ");
        if (msg->data_len < sizeof(struct gsm48_service_request*)) {
                DEBUGPC(DMM, "wrong sized message\n");
-               return gsm48_tx_mm_serv_rej(conn,
-                                           GSM48_REJECT_INCORRECT_MESSAGE);
+               return msc_gsm48_tx_mm_serv_rej(conn,
+                                               GSM48_REJECT_INCORRECT_MESSAGE);
        }
 
        if (msg->data_len < req->mi_len + 6) {
                DEBUGPC(DMM, "does not fit in packet\n");
-               return gsm48_tx_mm_serv_rej(conn,
-                                           GSM48_REJECT_INCORRECT_MESSAGE);
+               return msc_gsm48_tx_mm_serv_rej(conn,
+                                               GSM48_REJECT_INCORRECT_MESSAGE);
        }
 
        gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
@@ -716,8 +661,8 @@
                        mi_string);
        } else {
                DEBUGPC(DMM, "mi_type is not expected: %d\n", mi_type);
-               return gsm48_tx_mm_serv_rej(conn,
-                                           GSM48_REJECT_INCORRECT_MESSAGE);
+               return msc_gsm48_tx_mm_serv_rej(conn,
+                                               GSM48_REJECT_INCORRECT_MESSAGE);
        }
 
        osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_IDENTITY, (classmark2 + 
classmark2_len));
@@ -739,9 +684,6 @@
                /* logging already happened in msc_create_conn_fsm() */
                return rc;
        }
-
-       if (is_siemens_bts(conn->bts))
-               send_siemens_mrpci(msg->lchan, classmark2-1);
 
        vlr_proc_acc_req(conn->conn_fsm,
                         SUBSCR_CONN_E_ACCEPTED,
@@ -792,7 +734,6 @@
                     gsm48_mi_type_name(mi_type), mi_string);
                break;
        }
-
 
        /* TODO? We used to remember the subscriber's classmark1 here and
         * stored it in the old sqlite db, but now we store it in a conn that
@@ -1100,7 +1041,7 @@
 
        lai.plmn.mcc = conn->network->country_code;
        lai.plmn.mnc = conn->network->network_code;
-       lai.lac = conn->bts->location_area_code; /* (will be replaced by 
conn->lac soon) */
+       lai.lac = conn->lac;
 
        resp = (struct gsm48_pag_resp *) &gh->data[0];
        gsm48_paging_extract_mi(resp, msgb_l3len(msg) - sizeof(*gh),
@@ -1185,8 +1126,6 @@
 {
        struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 APP INF");
        struct gsm48_hdr *gh;
-
-       msg->lchan = conn->lchan;
 
        DEBUGP(DRR, "TX APPLICATION INFO id=0x%02x, len=%u\n",
                apdu_id, apdu_len);
@@ -1279,8 +1218,6 @@
        struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 TX SIMPLE");
        struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
 
-       msg->lchan = conn->lchan;
-
        gh->proto_discr = pdisc;
        gh->msg_type = msg_type;
 
@@ -1302,6 +1239,9 @@
        struct msgb *msg;
        unsigned char *data;
 
+#if BEFORE_MSCSPLIT
+       /* Re-enable this log output once we can obtain this information via
+        * A-interface, see OS#2391. */
        if (trans)
                if (trans->conn && trans->conn->lchan)
                        DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
@@ -1319,6 +1259,9 @@
        else
                DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
                        "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
+#else
+       DEBUGP(DCC, "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
+#endif
 
        mncc->msg_type = msg_type;
 
@@ -1362,8 +1305,6 @@
        }
        if (trans->cc.state != GSM_CSTATE_NULL)
                new_cc_state(trans, GSM_CSTATE_NULL);
-       if (trans->conn)
-               trau_mux_unmap(&trans->conn->lchan->ts->e1_link, 
trans->callref);
 }
 
 static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
@@ -1377,13 +1318,12 @@
 
        OSMO_ASSERT(!transt->conn);
 
-       /* check all tranactions (without lchan) for subscriber */
        switch (event) {
        case GSM_PAGING_SUCCEEDED:
                DEBUGP(DCC, "Paging subscr %s succeeded!\n",
                       vlr_subscr_msisdn_or_name(transt->vsub));
                OSMO_ASSERT(conn);
-               /* Assign lchan */
+               /* Assign conn */
                transt->conn = conn;
                /* send SETUP request to called party */
                gsm48_cc_tx_setup(transt, &transt->cc.msg);
@@ -1410,235 +1350,6 @@
        return 0;
 }
 
-static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int 
enable);
-
-/* handle audio path for handover */
-static int switch_for_handover(struct gsm_lchan *old_lchan,
-                       struct gsm_lchan *new_lchan)
-{
-       struct rtp_socket *old_rs, *new_rs, *other_rs;
-
-       /* Ask the new socket to send to the already known port. */
-       if (new_lchan->conn->mncc_rtp_bridge) {
-               LOGP(DHO, LOGL_DEBUG, "Forwarding RTP\n");
-               rsl_ipacc_mdcx(new_lchan,
-                                       old_lchan->abis_ip.connect_ip,
-                                       old_lchan->abis_ip.connect_port, 0);
-               return 0;
-       }
-
-       if (ipacc_rtp_direct) {
-               LOGP(DHO, LOGL_ERROR, "unable to handover in direct RTP 
mode\n");
-               return 0;
-       }
-
-       /* RTP Proxy mode */
-       new_rs = new_lchan->abis_ip.rtp_socket;
-       old_rs = old_lchan->abis_ip.rtp_socket;
-
-       if (!new_rs) {
-               LOGP(DHO, LOGL_ERROR, "no RTP socket for new_lchan\n");
-               return -EIO;
-       }
-
-       rsl_ipacc_mdcx_to_rtpsock(new_lchan);
-
-       if (!old_rs) {
-               LOGP(DHO, LOGL_ERROR, "no RTP socket for old_lchan\n");
-               return -EIO;
-       }
-
-       /* copy rx_action and reference to other sock */
-       new_rs->rx_action = old_rs->rx_action;
-       new_rs->tx_action = old_rs->tx_action;
-       new_rs->transmit = old_rs->transmit;
-
-       switch (old_lchan->abis_ip.rtp_socket->rx_action) {
-       case RTP_PROXY:
-               other_rs = old_rs->proxy.other_sock;
-               rtp_socket_proxy(new_rs, other_rs);
-               /* delete reference to other end socket to prevent
-                * rtp_socket_free() from removing the inverse reference */
-               old_rs->proxy.other_sock = NULL;
-               break;
-       case RTP_RECV_UPSTREAM:
-               new_rs->receive = old_rs->receive;
-               break;
-       case RTP_NONE:
-               break;
-       }
-
-       return 0;
-}
-
-static void maybe_switch_for_handover(struct gsm_lchan *lchan)
-{
-       struct gsm_lchan *old_lchan;
-       old_lchan = bsc_handover_pending(lchan);
-       if (old_lchan)
-               switch_for_handover(old_lchan, lchan);
-}
-
-/* some other part of the code sends us a signal */
-static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
-                                void *handler_data, void *signal_data)
-{
-       struct gsm_lchan *lchan = signal_data;
-       int rc;
-       struct gsm_network *net;
-       struct gsm_trans *trans;
-
-       if (subsys != SS_ABISIP)
-               return 0;
-
-       /* RTP bridge handling */
-       if (lchan->conn && lchan->conn->mncc_rtp_bridge)
-               return tch_rtp_signal(lchan, signal);
-
-       /* in case we use direct BTS-to-BTS RTP */
-       if (ipacc_rtp_direct)
-               return 0;
-
-       switch (signal) {
-       case S_ABISIP_CRCX_ACK:
-               /* in case we don't use direct BTS-to-BTS RTP */
-               /* the BTS has successfully bound a TCH to a local ip/port,
-                * which means we can connect our UDP socket to it */
-               if (lchan->abis_ip.rtp_socket) {
-                       rtp_socket_free(lchan->abis_ip.rtp_socket);
-                       lchan->abis_ip.rtp_socket = NULL;
-               }
-
-               lchan->abis_ip.rtp_socket = rtp_socket_create();
-               if (!lchan->abis_ip.rtp_socket)
-                       return -EIO;
-
-               rc = rtp_socket_connect(lchan->abis_ip.rtp_socket,
-                                  lchan->abis_ip.bound_ip,
-                                  lchan->abis_ip.bound_port);
-               if (rc < 0)
-                       return -EIO;
-
-               /* check if any transactions on this lchan still have
-                * a tch_recv_mncc request pending */
-               net = lchan->ts->trx->bts->network;
-               llist_for_each_entry(trans, &net->trans_list, entry) {
-                       if (trans->conn && trans->conn->lchan == lchan && 
trans->tch_recv) {
-                               DEBUGP(DCC, "pending tch_recv_mncc request\n");
-                               tch_recv_mncc(net, trans->callref, 1);
-                       }
-               }
-
-               /*
-                * TODO: this appears to be too early? Why not until after
-                * the handover detect or the handover complete?
-                *
-                * Do we have a handover pending for this new lchan? In that
-                * case re-route the audio from the old channel to the new one.
-                */
-               maybe_switch_for_handover(lchan);
-               break;
-       case S_ABISIP_DLCX_IND:
-               /* the BTS tells us a RTP stream has been disconnected */
-               if (lchan->abis_ip.rtp_socket) {
-                       rtp_socket_free(lchan->abis_ip.rtp_socket);
-                       lchan->abis_ip.rtp_socket = NULL;
-               }
-
-               break;
-       }
-
-       return 0;
-}
-
-/* map two ipaccess RTP streams onto each other */
-static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
-{
-       struct gsm_bts *bts = lchan->ts->trx->bts;
-       struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
-       enum gsm_chan_t lt = lchan->type, rt = remote_lchan->type;
-       enum gsm48_chan_mode lm = lchan->tch_mode, rm = remote_lchan->tch_mode;
-       int rc;
-
-       DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u,%s) and "
-              "(bts=%u,trx=%u,ts=%u,%s)\n",
-              bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
-              get_value_string(gsm_chan_t_names, lt),
-              remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr,
-              get_value_string(gsm_chan_t_names, rt));
-
-       if (bts->type != remote_bts->type) {
-               LOGP(DCC, LOGL_ERROR, "Cannot switch calls between different 
BTS types yet\n");
-               return -EINVAL;
-       }
-
-       if (lt != rt) {
-               LOGP(DCC, LOGL_ERROR, "Cannot patch through call with different"
-                    " channel types: local = %s, remote = %s\n",
-                    get_value_string(gsm_chan_t_names, lt),
-                    get_value_string(gsm_chan_t_names, rt));
-               return -EBADSLT;
-       }
-
-       if (lm != rm) {
-               LOGP(DCC, LOGL_ERROR, "Cannot patch through call with different"
-                    " channel modes: local = %s, remote = %s\n",
-                    get_value_string(gsm48_chan_mode_names, lm),
-                    get_value_string(gsm48_chan_mode_names, rm));
-               return -EMEDIUMTYPE;
-       }
-
-       // todo: map between different bts types
-       switch (bts->type) {
-       case GSM_BTS_TYPE_NANOBTS:
-       case GSM_BTS_TYPE_OSMOBTS:
-               if (!ipacc_rtp_direct) {
-                       if (!lchan->abis_ip.rtp_socket) {
-                               LOGP(DHO, LOGL_ERROR, "no RTP socket for "
-                                       "lchan\n");
-                               return -EIO;
-                       }
-                       if (!remote_lchan->abis_ip.rtp_socket) {
-                               LOGP(DHO, LOGL_ERROR, "no RTP socket for "
-                                       "remote_lchan\n");
-                               return -EIO;
-                       }
-
-                       /* connect the TCH's to our RTP proxy */
-                       rc = rsl_ipacc_mdcx_to_rtpsock(lchan);
-                       if (rc < 0)
-                               return rc;
-                       rc = rsl_ipacc_mdcx_to_rtpsock(remote_lchan);
-                       if (rc < 0)
-                               return rc;
-                       /* connect them with each other */
-                       rtp_socket_proxy(lchan->abis_ip.rtp_socket,
-                                        remote_lchan->abis_ip.rtp_socket);
-               } else {
-                       /* directly connect TCH RTP streams to each other */
-                       rc = rsl_ipacc_mdcx(lchan, 
remote_lchan->abis_ip.bound_ip,
-                                               
remote_lchan->abis_ip.bound_port,
-                                               
remote_lchan->abis_ip.rtp_payload2);
-                       if (rc < 0)
-                               return rc;
-                       rc = rsl_ipacc_mdcx(remote_lchan, 
lchan->abis_ip.bound_ip,
-                                               lchan->abis_ip.bound_port,
-                                               lchan->abis_ip.rtp_payload2);
-               }
-               break;
-       case GSM_BTS_TYPE_BS11:
-       case GSM_BTS_TYPE_RBS2000:
-       case GSM_BTS_TYPE_NOKIA_SITE:
-               trau_mux_map_lchan(lchan, remote_lchan);
-               break;
-       default:
-               LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 /* bridge channels of two transactions */
 static int tch_bridge(struct gsm_network *net, struct gsm_mncc_bridge *bridge)
 {
@@ -1654,81 +1365,8 @@
        /* Which subscriber do we want to track trans1 or trans2? */
        log_set_context(LOG_CTX_VLR_SUBSCR, trans1->vsub);
 
-       /* through-connect channel */
-       return tch_map(trans1->conn->lchan, trans2->conn->lchan);
-}
-
-/* enable receive of channels to MNCC upqueue */
-static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable)
-{
-       struct gsm_trans *trans;
-       struct gsm_lchan *lchan;
-       struct gsm_bts *bts;
-       int rc;
-
-       /* Find callref */
-       trans = trans_find_by_callref(net, callref);
-       if (!trans)
-               return -EIO;
-       if (!trans->conn)
-               return 0;
-
-       log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub);
-       lchan = trans->conn->lchan;
-       bts = lchan->ts->trx->bts;
-
-       /* store receive state */
-       trans->tch_recv = enable;
-
-       switch (bts->type) {
-       case GSM_BTS_TYPE_NANOBTS:
-       case GSM_BTS_TYPE_OSMOBTS:
-               if (ipacc_rtp_direct) {
-                       LOGP(DCC, LOGL_ERROR, "Error: RTP proxy is disabled\n");
-                       return -EINVAL;
-               }
-               /* In case, we don't have a RTP socket to the BTS yet, the BTS
-                * will not be connected to our RTP proxy and the socket will
-                * not be assigned to the application interface. This method
-                * will be called again, once the audio socket is created and
-                * connected. */
-               if (!lchan->abis_ip.rtp_socket) {
-                       DEBUGP(DCC, "queue tch_recv_mncc request (%d)\n", 
enable);
-                       return 0;
-               }
-               if (enable) {
-                       /* connect the TCH's to our RTP proxy */
-                       rc = rsl_ipacc_mdcx_to_rtpsock(lchan);
-                       if (rc < 0)
-                               return rc;
-                       /* assign socket to application interface */
-                       rtp_socket_upstream(lchan->abis_ip.rtp_socket,
-                               net, callref);
-               } else
-                       rtp_socket_upstream(lchan->abis_ip.rtp_socket,
-                               net, 0);
-               break;
-       case GSM_BTS_TYPE_BS11:
-       case GSM_BTS_TYPE_RBS2000:
-       case GSM_BTS_TYPE_NOKIA_SITE:
-               /* In case we don't have a TCH with correct mode, the TRAU muxer
-                * will not be asigned to the application interface. This is
-                * performed by switch_trau_mux() after successful handover or
-                * assignment. */
-               if (lchan->tch_mode == GSM48_CMODE_SIGN) {
-                       DEBUGP(DCC, "queue tch_recv_mncc request (%d)\n", 
enable);
-                       return 0;
-               }
-               if (enable)
-                       return trau_recv_lchan(lchan, callref);
-               return trau_mux_unmap(NULL, callref);
-               break;
-       default:
-               LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type);
-               return -EINVAL;
-       }
-
-       return 0;
+       /* future: msc_call_bridge(trans1, trans2); */
+       return -1;
 }
 
 static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
@@ -1868,7 +1506,7 @@
 
        memset(&setup, 0, sizeof(struct gsm_mncc));
        setup.callref = trans->callref;
-       setup.lchan_type = trans->conn->lchan->type;
+
        tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
        /* emergency setup is identified by msg_type */
        if (msg_type == GSM48_MT_CC_EMERG_SETUP)
@@ -1884,7 +1522,6 @@
                setup.fields |= MNCC_F_BEARER_CAP;
                gsm48_decode_bearer_cap(&setup.bearer_cap,
                                  TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
-               apply_codec_restrictions(trans->conn->bts, &setup.bearer_cap);
        }
        /* facility */
        if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
@@ -2024,7 +1661,7 @@
 
        memset(&call_conf, 0, sizeof(struct gsm_mncc));
        call_conf.callref = trans->callref;
-       call_conf.lchan_type = trans->conn->lchan->type;
+
        tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
 #if 0
        /* repeat */
@@ -2038,7 +1675,6 @@
                call_conf.fields |= MNCC_F_BEARER_CAP;
                gsm48_decode_bearer_cap(&call_conf.bearer_cap,
                                  TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
-               apply_codec_restrictions(trans->conn->bts, 
&call_conf.bearer_cap);
        }
        /* cause */
        if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
@@ -2728,7 +2364,6 @@
                modify.fields |= MNCC_F_BEARER_CAP;
                gsm48_decode_bearer_cap(&modify.bearer_cap,
                                  TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
-               apply_codec_restrictions(trans->conn->bts, &modify.bearer_cap);
        }
 
        new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
@@ -2771,7 +2406,6 @@
                modify.fields |= MNCC_F_BEARER_CAP;
                gsm48_decode_bearer_cap(&modify.bearer_cap,
                                  TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
-               apply_codec_restrictions(trans->conn->bts, &modify.bearer_cap);
        }
 
        new_cc_state(trans, GSM_CSTATE_ACTIVE);
@@ -2812,7 +2446,6 @@
                modify.fields |= GSM48_IE_BEARER_CAP;
                gsm48_decode_bearer_cap(&modify.bearer_cap,
                                  TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
-               apply_codec_restrictions(trans->conn->bts, &modify.bearer_cap);
        }
        /* cause */
        if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
@@ -2915,229 +2548,6 @@
        return mncc_recvmsg(trans->net, trans, MNCC_USERINFO_IND, &user);
 }
 
-static int _gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
-{
-       struct gsm_mncc *mode = arg;
-       struct gsm_lchan *lchan = trans->conn->lchan;
-
-       /*
-        * We were forced to make an assignment a lot earlier and
-        * we should avoid sending another assignment that might
-        * even lead to a different kind of lchan (TCH/F vs. TCH/H).
-        * In case of rtp-bridge it is too late to change things
-        * here.
-        */
-       if (trans->conn->mncc_rtp_bridge && lchan->tch_mode != GSM48_CMODE_SIGN)
-               return 0;
-
-       return gsm0808_assign_req(trans->conn, mode->lchan_mode,
-               trans->conn->lchan->type != GSM_LCHAN_TCH_H);
-}
-
-static void mncc_recv_rtp(struct gsm_network *net, uint32_t callref,
-               int cmd, uint32_t addr, uint16_t port, uint32_t payload_type,
-               uint32_t payload_msg_type)
-{
-       uint8_t data[sizeof(struct gsm_mncc)];
-       struct gsm_mncc_rtp *rtp;
-
-       memset(&data, 0, sizeof(data));
-       rtp = (struct gsm_mncc_rtp *) &data[0];
-
-       rtp->callref = callref;
-       rtp->msg_type = cmd;
-       rtp->ip = addr;
-       rtp->port = port;
-       rtp->payload_type = payload_type;
-       rtp->payload_msg_type = payload_msg_type;
-       mncc_recvmsg(net, NULL, cmd, (struct gsm_mncc *)data);
-}
-
-static void mncc_recv_rtp_sock(struct gsm_network *net, struct gsm_trans 
*trans, int cmd)
-{
-       struct gsm_lchan *lchan;
-       int msg_type;
-
-       lchan = trans->conn->lchan;
-       switch (lchan->abis_ip.rtp_payload) {
-       case RTP_PT_GSM_FULL:
-               msg_type = GSM_TCHF_FRAME;
-               break;
-       case RTP_PT_GSM_EFR:
-               msg_type = GSM_TCHF_FRAME_EFR;
-               break;
-       case RTP_PT_GSM_HALF:
-               msg_type = GSM_TCHH_FRAME;
-               break;
-       case RTP_PT_AMR:
-               msg_type = GSM_TCH_FRAME_AMR;
-               break;
-       default:
-               LOGP(DMNCC, LOGL_ERROR, "%s unknown payload type %d\n",
-                       gsm_lchan_name(lchan), lchan->abis_ip.rtp_payload);
-               msg_type = 0;
-               break;
-       }
-
-       return mncc_recv_rtp(net, trans->callref, cmd,
-                       lchan->abis_ip.bound_ip,
-                       lchan->abis_ip.bound_port,
-                       lchan->abis_ip.rtp_payload,
-                       msg_type);
-}
-
-static void mncc_recv_rtp_err(struct gsm_network *net, uint32_t callref, int 
cmd)
-{
-       return mncc_recv_rtp(net, callref, cmd, 0, 0, 0, 0);
-}
-
-static int tch_rtp_create(struct gsm_network *net, uint32_t callref)
-{
-       struct gsm_bts *bts;
-       struct gsm_lchan *lchan;
-       struct gsm_trans *trans;
-       enum gsm48_chan_mode m;
-
-       /* Find callref */
-       trans = trans_find_by_callref(net, callref);
-       if (!trans) {
-               LOGP(DMNCC, LOGL_ERROR, "RTP create for non-existing trans\n");
-               mncc_recv_rtp_err(net, callref, MNCC_RTP_CREATE);
-               return -EIO;
-       }
-       log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub);
-       if (!trans->conn) {
-               LOGP(DMNCC, LOGL_NOTICE, "RTP create for trans without conn\n");
-               mncc_recv_rtp_err(net, callref, MNCC_RTP_CREATE);
-               return 0;
-       }
-
-       lchan = trans->conn->lchan;
-       bts = lchan->ts->trx->bts;
-       if (!is_ipaccess_bts(bts)) {
-               /*
-                * I want this to be straight forward and have no audio flow
-                * through the nitb/osmo-mss system. This currently means that
-                * this will not work with BS11/Nokia type BTS. We would need
-                * to have a trau<->rtp bridge for these but still preferable
-                * in another process.
-                */
-               LOGP(DMNCC, LOGL_ERROR, "RTP create only works with IP 
systems\n");
-               mncc_recv_rtp_err(net, callref, MNCC_RTP_CREATE);
-               return -EINVAL;
-       }
-
-       trans->conn->mncc_rtp_bridge = 1;
-       /*
-        * *sigh* we need to pick a codec now. Pick the most generic one
-        * right now and hope we could fix that later on. This is very
-        * similiar to the routine above.
-        * Fallback to the internal MNCC mode to select a route.
-        */
-       if (lchan->tch_mode == GSM48_CMODE_SIGN) {
-               trans->conn->mncc_rtp_create_pending = 1;
-               m = mncc_codec_for_mode(lchan->type);
-               LOGP(DMNCC, LOGL_DEBUG, "RTP create: codec=%s, chan_type=%s\n",
-                    get_value_string(gsm48_chan_mode_names, m),
-                    get_value_string(gsm_chan_t_names, lchan->type));
-               return gsm0808_assign_req(trans->conn, m,
-                               lchan->type != GSM_LCHAN_TCH_H);
-       }
-
-       mncc_recv_rtp_sock(trans->net, trans, MNCC_RTP_CREATE);
-       return 0;
-}
-
-static int tch_rtp_connect(struct gsm_network *net, void *arg)
-{
-       struct gsm_lchan *lchan;
-       struct gsm_trans *trans;
-       struct gsm_mncc_rtp *rtp = arg;
-
-       /* Find callref */
-       trans = trans_find_by_callref(net, rtp->callref);
-       if (!trans) {
-               LOGP(DMNCC, LOGL_ERROR, "RTP connect for non-existing trans\n");
-               mncc_recv_rtp_err(net, rtp->callref, MNCC_RTP_CONNECT);
-               return -EIO;
-       }
-       log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub);
-       if (!trans->conn) {
-               LOGP(DMNCC, LOGL_ERROR, "RTP connect for trans without conn\n");
-               mncc_recv_rtp_err(net, rtp->callref, MNCC_RTP_CONNECT);
-               return 0;
-       }
-
-       lchan = trans->conn->lchan;
-       LOGP(DMNCC, LOGL_DEBUG, "RTP connect: codec=%s, chan_type=%s\n",
-                    get_value_string(gsm48_chan_mode_names,
-                                     mncc_codec_for_mode(lchan->type)),
-                    get_value_string(gsm_chan_t_names, lchan->type));
-
-       /* TODO: Check if payload_msg_type is compatible with what we have */
-       if (rtp->payload_type != lchan->abis_ip.rtp_payload) {
-               LOGP(DMNCC, LOGL_ERROR, "RTP connect with different RTP 
payload\n");
-               mncc_recv_rtp_err(net, rtp->callref, MNCC_RTP_CONNECT);
-       }
-
-       /*
-        * FIXME: payload2 can't be sent with MDCX as the osmo-bts code
-        * complains about both rtp and rtp payload2 being present in the
-        * same package!
-        */
-       trans->conn->mncc_rtp_connect_pending = 1;
-       return rsl_ipacc_mdcx(lchan, rtp->ip, rtp->port, 0);
-}
-
-static int tch_rtp_signal(struct gsm_lchan *lchan, int signal)
-{
-       struct gsm_network *net;
-       struct gsm_trans *tmp, *trans = NULL;
-
-       net = lchan->ts->trx->bts->network;
-       llist_for_each_entry(tmp, &net->trans_list, entry) {
-               if (!tmp->conn)
-                       continue;
-               if (tmp->conn->lchan != lchan && tmp->conn->ho_lchan != lchan)
-                       continue;
-               trans = tmp;
-               break;
-       }
-
-       if (!trans) {
-               LOGP(DMNCC, LOGL_ERROR, "%s IPA abis signal but no 
transaction.\n",
-                       gsm_lchan_name(lchan));
-               return 0;
-       }
-
-       switch (signal) {
-       case S_ABISIP_CRCX_ACK:
-               if (lchan->conn->mncc_rtp_create_pending) {
-                       lchan->conn->mncc_rtp_create_pending = 0;
-                       LOGP(DMNCC, LOGL_NOTICE, "%s sending pending RTP create 
ind.\n",
-                               gsm_lchan_name(lchan));
-                       mncc_recv_rtp_sock(net, trans, MNCC_RTP_CREATE);
-               }
-               /*
-                * TODO: this appears to be too early? Why not until after
-                * the handover detect or the handover complete?
-                */
-               maybe_switch_for_handover(lchan);
-               break;
-       case S_ABISIP_MDCX_ACK:
-               if (lchan->conn->mncc_rtp_connect_pending) {
-                       lchan->conn->mncc_rtp_connect_pending = 0;
-                       LOGP(DMNCC, LOGL_NOTICE, "%s sending pending RTP 
connect ind.\n",
-                               gsm_lchan_name(lchan));
-                       mncc_recv_rtp_sock(net, trans, MNCC_RTP_CONNECT);
-               }
-               break;
-       }
-
-       return 0;
-}
-
-
 static struct downstate {
        uint32_t        states;
        int             type;
@@ -3191,9 +2601,6 @@
         MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
        {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 
5.4.3.2 */
         MNCC_REL_REQ, gsm48_cc_tx_release},
-       /* special */
-       {ALL_STATES,
-        MNCC_LCHAN_MODIFY, _gsm48_lchan_modify},
 };
 
 #define DOWNSLLEN \
@@ -3205,7 +2612,6 @@
        int i, rc = 0;
        struct gsm_trans *trans = NULL, *transt;
        struct gsm_subscriber_connection *conn = NULL;
-       struct gsm_bts *bts = NULL;
        struct gsm_mncc *data = arg, rel;
 
        DEBUGP(DMNCC, "receive message %s\n", get_mncc_name(msg_type));
@@ -3218,60 +2624,17 @@
                        disconnect_bridge(net, arg, -rc);
                return rc;
        case MNCC_FRAME_DROP:
-               return tch_recv_mncc(net, data->callref, 0);
        case MNCC_FRAME_RECV:
-               return tch_recv_mncc(net, data->callref, 1);
        case MNCC_RTP_CREATE:
-               return tch_rtp_create(net, data->callref);
        case MNCC_RTP_CONNECT:
-               return tch_rtp_connect(net, arg);
        case MNCC_RTP_FREE:
-               /* unused right now */
-               return -EIO;
        case GSM_TCHF_FRAME:
        case GSM_TCHF_FRAME_EFR:
        case GSM_TCHH_FRAME:
        case GSM_TCH_FRAME_AMR:
-               /* Find callref */
-               trans = trans_find_by_callref(net, data->callref);
-               if (!trans) {
-                       LOGP(DMNCC, LOGL_ERROR, "TCH frame for non-existing 
trans\n");
-                       return -EIO;
-               }
-               log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub);
-               if (!trans->conn) {
-                       LOGP(DMNCC, LOGL_NOTICE, "TCH frame for trans without 
conn\n");
-                       return 0;
-               }
-               if (!trans->conn->lchan) {
-                       LOGP(DMNCC, LOGL_NOTICE, "TCH frame for trans without 
lchan\n");
-                       return 0;
-               }
-               if (trans->conn->lchan->type != GSM_LCHAN_TCH_F
-                && trans->conn->lchan->type != GSM_LCHAN_TCH_H) {
-                       /* This should be LOGL_ERROR or NOTICE, but
-                        * unfortuantely it happens for a couple of frames at
-                        * the beginning of every RTP connection */
-                       LOGP(DMNCC, LOGL_DEBUG, "TCH frame for lchan != 
TCH_F/TCH_H\n");
-                       return 0;
-               }
-               bts = trans->conn->lchan->ts->trx->bts;
-               switch (bts->type) {
-               case GSM_BTS_TYPE_NANOBTS:
-               case GSM_BTS_TYPE_OSMOBTS:
-                       if (!trans->conn->lchan->abis_ip.rtp_socket) {
-                               DEBUGP(DMNCC, "TCH frame to lchan without RTP 
connection\n");
-                               return 0;
-                       }
-                       return 
rtp_send_frame(trans->conn->lchan->abis_ip.rtp_socket, arg);
-               case GSM_BTS_TYPE_BS11:
-               case GSM_BTS_TYPE_RBS2000:
-               case GSM_BTS_TYPE_NOKIA_SITE:
-                       return trau_send_frame(trans->conn->lchan, arg);
-               default:
-                       LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", 
bts->type);
-               }
-               return -EINVAL;
+               LOGP(DMNCC, LOGL_ERROR, "RTP streams must be handled 
externally; %s not supported.\n",
+                    get_mncc_name(msg_type));
+               return -ENOTSUP;
        }
 
        memset(&rel, 0, sizeof(struct gsm_mncc));
@@ -3347,14 +2710,15 @@
                                         GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
                        return -ENOMEM;
                }
-               /* Find lchan */
+
+               /* Find conn */
                conn = connection_for_subscr(vsub);
 
-               /* If subscriber has no lchan */
+               /* If subscriber has no conn */
                if (!conn) {
                        /* find transaction with this subscriber already paging 
*/
                        llist_for_each_entry(transt, &net->trans_list, entry) {
-                               /* Transaction of our lchan? */
+                               /* Transaction of our conn? */
                                if (transt == trans ||
                                    transt->vsub != vsub)
                                        continue;
@@ -3372,7 +2736,7 @@
                        memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
 
                        /* Request a channel */
-                       trans->paging_request = subscr_request_channel(
+                       trans->paging_request = subscr_request_conn(
                                                        vsub,
                                                        RSL_CHANNEED_TCH_F,
                                                        setup_trig_pag_evt,
@@ -3386,7 +2750,8 @@
                        vlr_subscr_put(vsub);
                        return 0;
                }
-               /* Assign lchan */
+
+               /* Assign conn */
                trans->conn = msc_subscr_conn_get(conn);
                vlr_subscr_put(vsub);
        } else {
@@ -3399,7 +2764,7 @@
 
        /* if paging did not respond yet */
        if (!conn) {
-               DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
+               DEBUGP(DCC, "(sub %s) "
                        "Received '%s' from MNCC in paging state\n",
                        vlr_subscr_msisdn_or_name(trans->vsub),
                        get_mncc_name(msg_type));
@@ -3414,9 +2779,8 @@
                return rc;
        }
 
-       DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
+       DEBUGP(DCC, "(ti %02x sub %s) "
                "Received '%s' from MNCC in state %d (%s)\n",
-               conn->bts->nr, conn->lchan->ts->trx->nr, conn->lchan->ts->nr,
                trans->transaction_id,
                vlr_subscr_msisdn_or_name(trans->conn->vsub),
                get_mncc_name(msg_type), trans->cc.state,
@@ -3513,12 +2877,16 @@
        /* Find transaction */
        trans = trans_find_by_id(conn, GSM48_PDISC_CC, transaction_id);
 
+#if BEFORE_MSCSPLIT
+       /* Re-enable this log output once we can obtain this information via
+        * A-interface, see OS#2391. */
        DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
                "Received '%s' from MS in state %d (%s)\n",
                conn->bts->nr, conn->lchan->ts->trx->nr, conn->lchan->ts->nr,
                transaction_id, vlr_subscr_msisdn_or_name(conn->vsub),
                gsm48_cc_msg_name(msg_type), trans?(trans->cc.state):0,
                gsm48_cc_state_name(trans?(trans->cc.state):0));
+#endif
 
        /* Create transaction */
        if (!trans) {
@@ -3836,11 +3204,18 @@
                         net->gsup_server_port);
 }
 
-/*
- * This will be run by the linker when loading the DSO. We use it to
- * do system initialization, e.g. registration of signal handlers.
- */
-static __attribute__((constructor)) void on_dso_load_0408(void)
+/* This is a temporary shim merely to ensure that the unit tests still work. It
+ * shall be removed as soon as Iu and A interface paging is implemented. */
+int msc_fake_paging_request(struct vlr_subscr *vsub)
 {
-       osmo_signal_register_handler(SS_ABISIP, handle_abisip_signal, NULL);
+       LOGP(DMM, LOGL_ERROR, "Paging currently not implemented in the MSC.\n");
+       OSMO_ASSERT(false);
+}
+
+/* This is a temporary shim merely to ensure that the unit tests still work. It
+ * shall be removed as soon as Iu and A interface paging is implemented. */
+void msc_fake_paging_request_stop(struct vlr_subscr *vsub)
+{
+       LOGP(DMM, LOGL_ERROR, "Paging currently not implemented in the MSC.\n");
+       OSMO_ASSERT(false);
 }
diff --git a/src/libmsc/gsm_04_11.c b/src/libmsc/gsm_04_11.c
index 6ad944b..3255a3b 100644
--- a/src/libmsc/gsm_04_11.c
+++ b/src/libmsc/gsm_04_11.c
@@ -878,7 +878,7 @@
 }
 
 /* Take a SMS in gsm_sms structure and send it through an already
- * existing lchan. We also assume that the caller ensured this lchan already
+ * existing conn. We also assume that the caller ensured this conn already
  * has a SAPI3 RLL connection! */
 int gsm411_send_sms(struct gsm_subscriber_connection *conn, struct gsm_sms 
*sms)
 {
@@ -1004,7 +1004,7 @@
        struct gsm_subscriber_connection *conn;
        void *res;
 
-       /* check if we already have an open lchan to the subscriber.
+       /* check if we already have an open conn to the subscriber.
         * if yes, send the SMS this way */
        conn = connection_for_subscr(vsub);
        if (conn) {
@@ -1016,8 +1016,8 @@
        /* if not, we have to start paging */
        LOGP(DLSMS, LOGL_DEBUG, "Sending SMS: no connection open, start paging 
%s\n",
             vlr_subscr_name(vsub));
-       res = subscr_request_channel(vsub, RSL_CHANNEED_SDCCH,
-                                    paging_cb_send_sms, sms);
+       res = subscr_request_conn(vsub, RSL_CHANNEED_SDCCH, paging_cb_send_sms,
+                                 sms);
        if (!res) {
                send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, GSM_PAGING_BUSY);
                sms_free(sms);
diff --git a/src/libmsc/gsm_subscriber.c b/src/libmsc/gsm_subscriber.c
index e9b2e0e..69d79b0 100644
--- a/src/libmsc/gsm_subscriber.c
+++ b/src/libmsc/gsm_subscriber.c
@@ -41,43 +41,6 @@
 #include <openbsc/chan_alloc.h>
 #include <openbsc/vlr.h>
 
-void *tall_sub_req_ctx;
-
-int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq,
-                         gsm_cbfn *cb, void *cb_data);
-
-
-/*
- * Struct for pending channel requests. This is managed in the
- * llist_head requests of each subscriber. The reference counting
- * should work in such a way that a subscriber with a pending request
- * remains in memory.
- */
-struct subscr_request {
-       struct llist_head entry;
-
-       /* the callback data */
-       gsm_cbfn *cbfn;
-       void *param;
-};
-
-static struct bsc_subscr *vlr_subscr_to_bsc_sub(struct llist_head 
*bsc_subscribers,
-                                               struct vlr_subscr *vsub)
-{
-       struct bsc_subscr *sub;
-       /* TODO MSC split -- creating a BSC subscriber directly from MSC data
-        * structures in RAM. At some point the MSC will send a message to the
-        * BSC instead. */
-       sub = bsc_subscr_find_or_create_by_imsi(bsc_subscribers, vsub->imsi);
-       sub->tmsi = vsub->tmsi;
-       sub->lac = vsub->lac;
-       return sub;
-}
-
-/*
- * We got the channel assigned and can now hand this channel
- * over to one of our callbacks.
- */
 int subscr_paging_dispatch(unsigned int hooknum, unsigned int event,
                           struct msgb *msg, void *data, void *param)
 {
@@ -85,22 +48,12 @@
        struct gsm_subscriber_connection *conn = data;
        struct vlr_subscr *vsub = param;
        struct paging_signal_data sig_data;
-       struct bsc_subscr *bsub;
-       struct gsm_network *net;
 
        OSMO_ASSERT(vsub && vsub->cs.is_paging);
-       net = vsub->vlr->user_ctx;
 
-       /*
-        * Stop paging on all other BTS. E.g. if this is
-        * the first timeout on a BTS then the others will
-        * timeout soon as well. Let's just stop everything
-        * and forget we wanted to page.
-        */
-
-       bsub = vlr_subscr_to_bsc_sub(conn->network->bsc_subscribers, vsub);
-       paging_request_stop(&net->bts_list, NULL, bsub, NULL, NULL);
-       bsc_subscr_put(bsub);
+       /* FIXME: implement stop paging in libmsc;
+        * faking it for the unit tests to still work */
+       msc_fake_paging_request_stop(vsub);
 
        /* Inform parts of the system we don't know */
        sig_data.vsub   = vsub;
@@ -126,22 +79,21 @@
        return 0;
 }
 
-struct subscr_request *subscr_request_channel(struct vlr_subscr *vsub,
-                                             int channel_type,
-                                             gsm_cbfn *cbfn, void *param)
+struct subscr_request *subscr_request_conn(struct vlr_subscr *vsub, int 
channel_type, gsm_cbfn *cbfn,
+                                          void *param)
 {
        int rc;
        struct subscr_request *request;
-       struct bsc_subscr *bsub;
-       struct gsm_network *net = vsub->vlr->user_ctx;
 
        /* Start paging.. we know it is async so we can do it before */
        if (!vsub->cs.is_paging) {
                LOGP(DMM, LOGL_DEBUG, "Subscriber %s not paged yet.\n",
                     vlr_subscr_name(vsub));
-               bsub = vlr_subscr_to_bsc_sub(net->bsc_subscribers, vsub);
-               rc = paging_request(net, bsub, channel_type, NULL, NULL);
-               bsc_subscr_put(bsub);
+
+               /* FIXME: implement paging in libmsc;
+                * faking it for the unit tests to still work */
+               rc = msc_fake_paging_request(vsub);
+
                if (rc <= 0) {
                        LOGP(DMM, LOGL_ERROR, "Subscriber %s paging failed: 
%d\n",
                             vlr_subscr_name(vsub), rc);
diff --git a/src/libmsc/mncc_builtin.c b/src/libmsc/mncc_builtin.c
index 067cc92..ac6e734 100644
--- a/src/libmsc/mncc_builtin.c
+++ b/src/libmsc/mncc_builtin.c
@@ -65,21 +65,6 @@
        return NULL;
 }
 
-uint8_t mncc_codec_for_mode(int lchan_type)
-{
-       /* FIXME: check codec capabilities of the phone */
-
-       if (lchan_type != GSM_LCHAN_TCH_H)
-               return mncc_int.def_codec[0];
-       else
-               return mncc_int.def_codec[1];
-}
-
-static uint8_t determine_lchan_mode(struct gsm_mncc *setup)
-{
-       return mncc_codec_for_mode(setup->lchan_type);
-}
-
 /* on incoming call, look up database and send setup to remote subscr. */
 static int mncc_setup_ind(struct gsm_call *call, int msg_type,
                          struct gsm_mncc *setup)
@@ -137,9 +122,7 @@
        /* modify mode */
        memset(&mncc, 0, sizeof(struct gsm_mncc));
        mncc.callref = call->callref;
-       mncc.lchan_mode = determine_lchan_mode(setup);
-       DEBUGP(DMNCC, "(call %x) Modify channel mode: %s\n", call->callref,
-              get_value_string(gsm48_chan_mode_names, mncc.lchan_mode));
+       DEBUGP(DMNCC, "(call %x) Modify channel mode\n", call->callref);
        mncc_tx_to_cc(call->net, MNCC_LCHAN_MODIFY, &mncc);
 
        /* send setup to remote */
@@ -206,10 +189,6 @@
        bridge.callref[0] = call->callref;
        bridge.callref[1] = call->remote_ref;
        DEBUGP(DMNCC, "(call %x) Bridging with remote.\n", call->callref);
-
-       /* in direct mode, we always have to bridge the channels */
-       if (ipacc_rtp_direct)
-               return mncc_tx_to_cc(call->net, MNCC_BRIDGE, &bridge);
 
        /* proxy mode */
        if (!net->handover.active) {
@@ -279,28 +258,6 @@
        return 0;
 }
 
-/* receiving a (speech) traffic frame from the BSC code */
-static int mncc_rcv_data(struct gsm_call *call, int msg_type,
-                        struct gsm_data_frame *dfr)
-{
-       struct gsm_trans *remote_trans;
-
-       remote_trans = trans_find_by_callref(call->net, call->remote_ref);
-
-       /* this shouldn't really happen */
-       if (!remote_trans || !remote_trans->conn) {
-               LOGP(DMNCC, LOGL_ERROR, "No transaction or transaction without 
lchan?!?\n");
-               return -EIO;
-       }
-
-       /* RTP socket of remote end has meanwhile died */
-       if (!remote_trans->conn->lchan->abis_ip.rtp_socket)
-               return -EIO;
-
-       return rtp_send_frame(remote_trans->conn->lchan->abis_ip.rtp_socket, 
dfr);
-}
-
-
 /* Internal MNCC handler input function (from CC -> MNCC -> here) */
 int int_mncc_recv(struct gsm_network *net, struct msgb *msg)
 {
@@ -346,7 +303,8 @@
        }
 
        if (mncc_is_data_frame(msg_type)) {
-               rc = mncc_rcv_data(call, msg_type, arg);
+               LOGP(DMNCC, LOGL_ERROR, "(call %x) Received data frame, which 
is not supported.\n",
+                    call->callref);
                goto out_free;
        }
 
@@ -364,7 +322,6 @@
                break;
        case MNCC_CALL_CONF_IND:
                /* we now need to MODIFY the channel */
-               data->lchan_mode = determine_lchan_mode(data);
                mncc_tx_to_cc(call->net, MNCC_LCHAN_MODIFY, data);
                break;
        case MNCC_ALERT_IND:
diff --git a/src/libmsc/mncc_sock.c b/src/libmsc/mncc_sock.c
index 0efe3a1..0c696f2 100644
--- a/src/libmsc/mncc_sock.c
+++ b/src/libmsc/mncc_sock.c
@@ -224,7 +224,6 @@
        hello->called_offset = offsetof(struct gsm_mncc, called);
        hello->signal_offset = offsetof(struct gsm_mncc, signal);
        hello->emergency_offset = offsetof(struct gsm_mncc, emergency);
-       hello->lchan_type_offset = offsetof(struct gsm_mncc, lchan_type);
 
        msgb_enqueue(&mncc->net->upqueue, msg);
        mncc->conn_bfd.when |= BSC_FD_WRITE;
diff --git a/src/libmsc/msc_ifaces.c b/src/libmsc/msc_ifaces.c
new file mode 100644
index 0000000..001fcba
--- /dev/null
+++ b/src/libmsc/msc_ifaces.c
@@ -0,0 +1,84 @@
+/* Implementation for MSC decisions which interface to send messages out on. */
+
+/* (C) 2016 by sysmocom s.m.f.c GmbH <[email protected]>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <osmocom/core/logging.h>
+
+#include <openbsc/debug.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/msc_ifaces.h>
+
+static int msc_tx(struct gsm_subscriber_connection *conn, struct msgb *msg)
+{
+       switch (conn->via_ran) {
+       /* FUTURE 
+       case RAN_GERAN_A:
+               msg->dst = conn;
+               return a_tx(msg);
+
+       case RAN_UTRAN_IU:
+               msg->dst = conn->iu.ue_ctx;
+               return iu_tx(msg, 0);
+       */
+       default:
+               LOGP(DMSC, LOGL_ERROR,
+                    "msc_tx(): conn->via_ran invalid (%d)\n",
+                    conn->via_ran);
+               return -1;
+       }
+}
+
+
+int msc_tx_dtap(struct gsm_subscriber_connection *conn,
+               struct msgb *msg)
+{
+       return msc_tx(conn, msg);
+}
+
+
+/* 9.2.5 CM service accept */
+int msc_gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn)
+{
+       struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SERV ACC");
+       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+
+       gh->proto_discr = GSM48_PDISC_MM;
+       gh->msg_type = GSM48_MT_MM_CM_SERV_ACC;
+
+       DEBUGP(DMM, "-> CM SERVICE ACCEPT\n");
+
+       return msc_tx_dtap(conn, msg);
+}
+
+/* 9.2.6 CM service reject */
+int msc_gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
+                            enum gsm48_reject_value value)
+{
+       struct msgb *msg;
+
+       msg = gsm48_create_mm_serv_rej(value);
+       if (!msg) {
+               LOGP(DMM, LOGL_ERROR, "Failed to allocate CM Service 
Reject.\n");
+               return -1;
+       }
+
+       DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
+
+       return msc_tx_dtap(conn, msg);
+}
diff --git a/src/libmsc/osmo_msc.c b/src/libmsc/osmo_msc.c
index 95e5818..c847b78 100644
--- a/src/libmsc/osmo_msc.c
+++ b/src/libmsc/osmo_msc.c
@@ -21,6 +21,7 @@
  *
  */
 
+#include <openbsc/osmo_msc.h>
 #include <openbsc/bsc_api.h>
 #include <openbsc/debug.h>
 #include <openbsc/transaction.h>
@@ -69,9 +70,10 @@
        osmo_fsm_inst_dispatch(conn->conn_fsm, SUBSCR_CONN_E_BUMP, NULL);
 }
 
-/* Receive a COMPLETE LAYER3 INFO from BSC */
-static int msc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb 
*msg,
-                       uint16_t chosen_channel)
+/* receive a Level 3 Complete message and return MSC_CONN_ACCEPT or
+ * MSC_CONN_REJECT */
+static int msc_compl_l3(struct gsm_subscriber_connection *conn,
+                       struct msgb *msg, uint16_t chosen_channel)
 {
        /* Ownership of the gsm_subscriber_connection is still a bit mucky
         * between libbsc and libmsc. In libmsc, we use ref counting, but not
@@ -87,7 +89,7 @@
                /* keep the use_count reserved, libbsc will discard. If we
                 * released the ref count and discarded here, libbsc would
                 * double-free. And we will not change bsc_api semantics. */
-               return BSC_API_CONN_POL_REJECT;
+               return MSC_CONN_REJECT;
        }
        DEBUGP(DMM, "compl_l3: Keeping conn\n");
 
@@ -96,7 +98,7 @@
 
        /* If this should be kept, the conn->conn_fsm has placed a use_count */
        msc_subscr_conn_put(conn);
-       return BSC_API_CONN_POL_ACCEPT;
+       return MSC_CONN_ACCEPT;
 
 #if 0
        /*
@@ -105,14 +107,14 @@
         * pending transaction or ongoing operation.
         */
        if (conn->silent_call)
-               return BSC_API_CONN_POL_ACCEPT;
-       if (conn->sec_operation || conn->anch_operation)
-               return BSC_API_CONN_POL_ACCEPT;
+               return MSC_CONN_ACCEPT;
+       if (conn->loc_operation || conn->sec_operation || conn->anch_operation)
+               return MSC_CONN_ACCEPT;
        if (trans_has_conn(conn))
-               return BSC_API_CONN_POL_ACCEPT;
+               return MSC_CONN_ACCEPT;
 
        LOGP(DRR, LOGL_INFO, "MSC Complete L3: Rejecting connection.\n");
-       return BSC_API_CONN_POL_REJECT;
+       return MSC_CONN_REJECT;
 #endif
 }
 
diff --git a/src/libmsc/silent_call.c b/src/libmsc/silent_call.c
index 6f3fbf2..5fad4f4 100644
--- a/src/libmsc/silent_call.c
+++ b/src/libmsc/silent_call.c
@@ -52,8 +52,12 @@
 
        switch (event) {
        case GSM_PAGING_SUCCEEDED:
+#if BEFORE_MSCSPLIT
+               /* Re-enable this log output once we can obtain this 
information via
+                * A-interface, see OS#2391. */
                DEBUGPC(DLSMS, "success, using Timeslot %u on ARFCN %u\n",
                        conn->lchan->ts->nr, conn->lchan->ts->trx->arfcn);
+#endif
                conn->silent_call = 1;
                msc_subscr_conn_get(conn);
                /* increment lchan reference count */
@@ -126,7 +130,10 @@
 {
        struct subscr_request *req;
 
-       req = subscr_request_channel(vsub, type, paging_cb_silent, data);
+       /* FIXME the VTY command allows selecting a silent call channel type.
+        * This doesn't apply to the situation after MSCSPLIT with an
+        * A-interface. */
+       req = subscr_request_conn(vsub, type, paging_cb_silent, data);
        return req != NULL;
 }
 
@@ -143,8 +150,12 @@
        if (!conn->silent_call)
                return -EINVAL;
 
+#if BEFORE_MSCSPLIT
+       /* Re-enable this log output once we can obtain this information via
+        * A-interface, see OS#2391. */
        DEBUGPC(DLSMS, "Stopping silent call using Timeslot %u on ARFCN %u\n",
                conn->lchan->ts->nr, conn->lchan->ts->trx->arfcn);
+#endif
 
        conn->silent_call = 0;
        msc_subscr_conn_put(conn);
diff --git a/src/libmsc/smpp_openbsc.c b/src/libmsc/smpp_openbsc.c
index f06eb7d..24a4653 100644
--- a/src/libmsc/smpp_openbsc.c
+++ b/src/libmsc/smpp_openbsc.c
@@ -423,6 +423,8 @@
        build_tlv(req_tlv, &tlv);
 }
 
+#if BEFORE_MSCSPLIT
+/* We currently have no lchan information. Re-add after A-interface, see 
OS#2390. */
 /* Append the Osmocom vendor-specific additional TLVs to a SMPP msg */
 static void append_osmo_tlvs(tlv_t **req_tlv, const struct gsm_lchan *lchan)
 {
@@ -461,6 +463,7 @@
                                   (uint8_t *)vsub->imei, imei_len+1);
        }
 }
+#endif
 
 struct {
        uint32_t smpp_status_code;
@@ -680,8 +683,11 @@
                memcpy(deliver.short_message, sms->user_data, 
deliver.sm_length);
        }
 
+#if BEFORE_MSCSPLIT
+       /* We currently have no lchan information. Re-add after A-interface, 
see OS#2390. */
        if (esme->acl && esme->acl->osmocom_ext && conn->lchan)
                append_osmo_tlvs(&deliver.tlv, conn->lchan);
+#endif
 
        ret = smpp_tx_deliver(esme, &deliver);
        if (ret < 0)
diff --git a/src/libmsc/vty_interface_layer3.c 
b/src/libmsc/vty_interface_layer3.c
index c393a8f..0106f91 100644
--- a/src/libmsc/vty_interface_layer3.c
+++ b/src/libmsc/vty_interface_layer3.c
@@ -553,57 +553,6 @@
        return CMD_WARNING;
 }
 
-DEFUN(ena_subscr_handover,
-      ena_subscr_handover_cmd,
-      "subscriber " SUBSCR_TYPES " ID handover BTS_NR",
-       SUBSCR_HELP "Handover the active connection\n"
-       "Number of the BTS to handover to\n")
-{
-       int ret;
-       struct gsm_subscriber_connection *conn;
-       struct gsm_bts *bts;
-       struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-       struct vlr_subscr *vsub =
-                       get_vsub_by_argv(gsmnet, argv[0], argv[1]);
-
-       if (!vsub) {
-               vty_out(vty, "%% No subscriber found for %s %s.%s",
-                       argv[0], argv[1], VTY_NEWLINE);
-               return CMD_WARNING;
-       }
-
-       conn = connection_for_subscr(vsub);
-       if (!conn) {
-               vty_out(vty, "%% No active connection for subscriber %s %s.%s",
-                       argv[0], argv[1], VTY_NEWLINE);
-               vlr_subscr_put(vsub);
-               return CMD_WARNING;
-       }
-
-       bts = gsm_bts_num(gsmnet, atoi(argv[2]));
-       if (!bts) {
-               vty_out(vty, "%% BTS with number(%d) could not be found.%s",
-                       atoi(argv[2]), VTY_NEWLINE);
-               vlr_subscr_put(vsub);
-               return CMD_WARNING;
-       }
-
-       /* now start the handover */
-       ret = bsc_handover_start(conn->lchan, bts);
-       if (ret != 0) {
-               vty_out(vty, "%% Handover failed with errno %d.%s",
-                       ret, VTY_NEWLINE);
-       } else {
-               vty_out(vty, "%% Handover started from %s",
-                       gsm_lchan_name(conn->lchan));
-               vty_out(vty, " to %s.%s", gsm_lchan_name(conn->ho_lchan),
-                       VTY_NEWLINE);
-       }
-
-       vlr_subscr_put(vsub);
-       return CMD_SUCCESS;
-}
-
 #define A3A8_ALG_TYPES "(none|xor|comp128v1)"
 #define A3A8_ALG_HELP                  \
        "Use No A3A8 algorithm\n"       \
@@ -652,9 +601,7 @@
 
        switch (signal) {
        case S_SCALL_SUCCESS:
-               vty_out(vty, "%% silent call on ARFCN %u timeslot %u%s",
-                       sigdata->conn->lchan->ts->trx->arfcn, 
sigdata->conn->lchan->ts->nr,
-                       VTY_NEWLINE);
+               vty_out(vty, "%% silent call success%s", VTY_NEWLINE);
                break;
        case S_SCALL_EXPIRED:
                vty_out(vty, "%% silent call expired paging%s", VTY_NEWLINE);
@@ -670,7 +617,6 @@
 {
        struct gsm_network *net = gsmnet_from_vty(vty);
 
-       openbsc_vty_print_statistics(vty, net);
        vty_out(vty, "Location Update         : %lu attach, %lu normal, %lu 
periodic%s",
                net->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
                net->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
@@ -1055,7 +1001,6 @@
        install_element(ENABLE_NODE, &ena_subscr_extension_cmd);
        install_element(ENABLE_NODE, &ena_subscr_authorized_cmd);
        install_element(ENABLE_NODE, &ena_subscr_a3a8_cmd);
-       install_element(ENABLE_NODE, &ena_subscr_handover_cmd);
        install_element(ENABLE_NODE, &subscriber_purge_cmd);
        install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
        install_element(ENABLE_NODE, &smsqueue_max_cmd);
diff --git a/tests/bsc/Makefile.am b/tests/bsc/Makefile.am
index 9de4145..904bdfc 100644
--- a/tests/bsc/Makefile.am
+++ b/tests/bsc/Makefile.am
@@ -32,7 +32,6 @@
 
 bsc_test_LDADD = \
        $(top_builddir)/src/libbsc/libbsc.a \
-       $(top_builddir)/src/libmsc/libmsc.a \
        $(top_builddir)/src/libcommon-cs/libcommon-cs.a \
        $(top_builddir)/src/libmgcp/libmgcp.a \
        $(top_builddir)/src/libtrau/libtrau.a \
diff --git a/tests/channel/Makefile.am b/tests/channel/Makefile.am
index c7164b4..dd78bdc 100644
--- a/tests/channel/Makefile.am
+++ b/tests/channel/Makefile.am
@@ -24,7 +24,6 @@
        $(NULL)
 
 channel_test_LDADD = \
-       $(top_builddir)/src/libmsc/libmsc.a \
        $(top_builddir)/src/libbsc/libbsc.a \
        $(top_builddir)/src/libvlr/libvlr.a \
        $(top_builddir)/src/libcommon-cs/libcommon-cs.a \
diff --git a/tests/db/Makefile.am b/tests/db/Makefile.am
index 0eed5cd..df421d8 100644
--- a/tests/db/Makefile.am
+++ b/tests/db/Makefile.am
@@ -32,9 +32,7 @@
        $(NULL)
 
 db_test_LDADD = \
-       $(top_builddir)/src/libbsc/libbsc.a \
        $(top_builddir)/src/libmsc/libmsc.a \
-       $(top_builddir)/src/libbsc/libbsc.a \
        $(top_builddir)/src/libcommon-cs/libcommon-cs.a \
        $(top_builddir)/src/libtrau/libtrau.a \
        $(top_builddir)/src/libcommon/libcommon.a \
diff --git a/tests/gsm0408/gsm0408_test.c b/tests/gsm0408/gsm0408_test.c
index 5a8c6ca..1b326ee 100644
--- a/tests/gsm0408/gsm0408_test.c
+++ b/tests/gsm0408/gsm0408_test.c
@@ -182,7 +182,7 @@
 static inline void test_si2q_u(void)
 {
        struct gsm_bts *bts;
-       struct gsm_network *network = bsc_network_init(tall_bsc_ctx, 1, 1, 
NULL);
+       struct gsm_network *network = bsc_network_init(NULL, 1, 1, NULL);
        printf("Testing SYSINFO_TYPE_2quater UARFCN generation:\n");
 
        if (!network)
@@ -210,7 +210,7 @@
 static inline void test_si2q_e(void)
 {
        struct gsm_bts *bts;
-       struct gsm_network *network = bsc_network_init(tall_bsc_ctx, 1, 1, 
NULL);
+       struct gsm_network *network = bsc_network_init(NULL, 1, 1, NULL);
        printf("Testing SYSINFO_TYPE_2quater EARFCN generation:\n");
 
        if (!network)
diff --git a/tests/msc_vlr/Makefile.am b/tests/msc_vlr/Makefile.am
index ebbfb5c..71450af 100644
--- a/tests/msc_vlr/Makefile.am
+++ b/tests/msc_vlr/Makefile.am
@@ -60,8 +60,8 @@
        -Wl,--wrap=gsup_client_create \
        -Wl,--wrap=gsup_client_send \
        -Wl,--wrap=gsm0808_submit_dtap \
-       -Wl,--wrap=paging_request \
-       -Wl,--wrap=paging_request_stop \
+       -Wl,--wrap=msc_fake_paging_request \
+       -Wl,--wrap=msc_fake_paging_request_stop \
        -Wl,--wrap=gsm340_gen_scts \
        -Wl,--wrap=RAND_bytes \
        $(NULL)
diff --git a/tests/msc_vlr/msc_vlr_test_gsm_authen.err 
b/tests/msc_vlr/msc_vlr_test_gsm_authen.err
index 8f93435..497b7d3 100644
--- a/tests/msc_vlr/msc_vlr_test_gsm_authen.err
+++ b/tests/msc_vlr/msc_vlr_test_gsm_authen.err
@@ -270,9 +270,8 @@
   llist_count(&vsub->cs.requests) == 0
 DREF VLR subscr MSISDN:46071 usage increases to: 3
 DMM Subscriber MSISDN:46071 not paged yet.
-  BTS/BSC sends out paging request to IMSI:901700000004620 for channel type 1
-  strcmp(paging_expecting_imsi, sub->imsi) == 0
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
+  BTS/BSC sends out paging request to MSISDN:46071
+  strcmp(paging_expecting_imsi, vsub->imsi) == 0
 DREF VLR subscr MSISDN:46071 usage increases to: 4
   llist_count(&vsub->cs.requests) == 1
 DREF VLR subscr MSISDN:46071 usage decreases to: 3
@@ -351,7 +350,6 @@
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event 
SUBSCR_CONN_E_ACCEPTED
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: 
SUBSCR_CONN_FROM_PAGING_RESP
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to 
SUBSCR_CONN_S_ACCEPTED
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
 DREF VLR subscr MSISDN:46071 usage increases to: 5
 DREF MSISDN:46071: MSC conn use + 1 == 3
 - DTAP --> MS: 
09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
@@ -734,9 +732,8 @@
   llist_count(&vsub->cs.requests) == 0
 DREF VLR subscr MSISDN:46071 usage increases to: 3
 DMM Subscriber MSISDN:46071 not paged yet.
-  BTS/BSC sends out paging request to IMSI:901700000004620 for channel type 1
+  BTS/BSC sends out paging request to MSISDN:46071
   paging_expecting_tmsi == 0x03020100
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
 DREF VLR subscr MSISDN:46071 usage increases to: 4
   llist_count(&vsub->cs.requests) == 1
 DREF VLR subscr MSISDN:46071 usage decreases to: 3
@@ -815,7 +812,6 @@
 DVLR Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: Received Event 
SUBSCR_CONN_E_ACCEPTED
 DVLR Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_PAGING_RESP
 DVLR Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: state_chg to 
SUBSCR_CONN_S_ACCEPTED
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
 DREF VLR subscr MSISDN:46071 usage increases to: 5
 DREF MSISDN:46071: MSC conn use + 1 == 3
 - DTAP --> MS: 
09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
@@ -1762,9 +1758,8 @@
   llist_count(&vsub->cs.requests) == 0
 DREF VLR subscr MSISDN:42342 usage increases to: 3
 DMM Subscriber MSISDN:42342 not paged yet.
-  BTS/BSC sends out paging request to IMSI:901700000010650 for channel type 1
-  strcmp(paging_expecting_imsi, sub->imsi) == 0
-DREF BSC subscr IMSI:901700000010650 usage decreases to: 0
+  BTS/BSC sends out paging request to MSISDN:42342
+  strcmp(paging_expecting_imsi, vsub->imsi) == 0
 DREF VLR subscr MSISDN:42342 usage increases to: 4
   llist_count(&vsub->cs.requests) == 1
 DREF VLR subscr MSISDN:42342 usage decreases to: 3
@@ -1843,7 +1838,6 @@
 DVLR Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: Received Event 
SUBSCR_CONN_E_ACCEPTED
 DVLR Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: 
SUBSCR_CONN_FROM_PAGING_RESP
 DVLR Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: state_chg to 
SUBSCR_CONN_S_ACCEPTED
-DREF BSC subscr IMSI:901700000010650 usage decreases to: 0
 DREF VLR subscr MSISDN:42342 usage increases to: 5
 DREF MSISDN:42342: MSC conn use + 1 == 3
 - DTAP --> MS: 
09015801000791447758100650004c0005802443f2000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
diff --git a/tests/msc_vlr/msc_vlr_test_gsm_ciph.err 
b/tests/msc_vlr/msc_vlr_test_gsm_ciph.err
index 4543ace..e241429 100644
--- a/tests/msc_vlr/msc_vlr_test_gsm_ciph.err
+++ b/tests/msc_vlr/msc_vlr_test_gsm_ciph.err
@@ -287,9 +287,8 @@
   llist_count(&vsub->cs.requests) == 0
 DREF VLR subscr MSISDN:46071 usage increases to: 3
 DMM Subscriber MSISDN:46071 not paged yet.
-  BTS/BSC sends out paging request to IMSI:901700000004620 for channel type 1
-  strcmp(paging_expecting_imsi, sub->imsi) == 0
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
+  BTS/BSC sends out paging request to MSISDN:46071
+  strcmp(paging_expecting_imsi, vsub->imsi) == 0
 DREF VLR subscr MSISDN:46071 usage increases to: 4
   llist_count(&vsub->cs.requests) == 1
 DREF VLR subscr MSISDN:46071 usage decreases to: 3
@@ -387,7 +386,6 @@
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event 
SUBSCR_CONN_E_ACCEPTED
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: 
SUBSCR_CONN_FROM_PAGING_RESP
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to 
SUBSCR_CONN_S_ACCEPTED
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
 DREF VLR subscr MSISDN:46071 usage increases to: 5
 DREF MSISDN:46071: MSC conn use + 1 == 2
 - DTAP --> MS: 
09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
@@ -786,9 +784,8 @@
   llist_count(&vsub->cs.requests) == 0
 DREF VLR subscr MSISDN:46071 usage increases to: 3
 DMM Subscriber MSISDN:46071 not paged yet.
-  BTS/BSC sends out paging request to IMSI:901700000004620 for channel type 1
+  BTS/BSC sends out paging request to MSISDN:46071
   paging_expecting_tmsi == 0x03020100
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
 DREF VLR subscr MSISDN:46071 usage increases to: 4
   llist_count(&vsub->cs.requests) == 1
 DREF VLR subscr MSISDN:46071 usage decreases to: 3
@@ -886,7 +883,6 @@
 DVLR Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: Received Event 
SUBSCR_CONN_E_ACCEPTED
 DVLR Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_PAGING_RESP
 DVLR Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: state_chg to 
SUBSCR_CONN_S_ACCEPTED
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
 DREF VLR subscr MSISDN:46071 usage increases to: 5
 DREF MSISDN:46071: MSC conn use + 1 == 2
 - DTAP --> MS: 
09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
diff --git a/tests/msc_vlr/msc_vlr_test_no_authen.err 
b/tests/msc_vlr/msc_vlr_test_no_authen.err
index 12b6c69..bc45367 100644
--- a/tests/msc_vlr/msc_vlr_test_no_authen.err
+++ b/tests/msc_vlr/msc_vlr_test_no_authen.err
@@ -186,9 +186,8 @@
   llist_count(&vsub->cs.requests) == 0
 DREF VLR subscr MSISDN:46071 usage increases to: 3
 DMM Subscriber MSISDN:46071 not paged yet.
-  BTS/BSC sends out paging request to IMSI:901700000004620 for channel type 1
-  strcmp(paging_expecting_imsi, sub->imsi) == 0
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
+  BTS/BSC sends out paging request to MSISDN:46071
+  strcmp(paging_expecting_imsi, vsub->imsi) == 0
 DREF VLR subscr MSISDN:46071 usage increases to: 4
   llist_count(&vsub->cs.requests) == 1
 DREF VLR subscr MSISDN:46071 usage decreases to: 3
@@ -227,7 +226,6 @@
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event 
SUBSCR_CONN_E_ACCEPTED
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: 
SUBSCR_CONN_FROM_PAGING_RESP
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to 
SUBSCR_CONN_S_ACCEPTED
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
 DREF VLR subscr MSISDN:46071 usage increases to: 6
 DREF MSISDN:46071: MSC conn use + 1 == 3
 - DTAP --> MS: 
09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
@@ -528,9 +526,8 @@
   llist_count(&vsub->cs.requests) == 0
 DREF VLR subscr MSISDN:46071 usage increases to: 3
 DMM Subscriber MSISDN:46071 not paged yet.
-  BTS/BSC sends out paging request to IMSI:901700000004620 for channel type 1
+  BTS/BSC sends out paging request to MSISDN:46071
   paging_expecting_tmsi == 0x03020100
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
 DREF VLR subscr MSISDN:46071 usage increases to: 4
   llist_count(&vsub->cs.requests) == 1
 DREF VLR subscr MSISDN:46071 usage decreases to: 3
@@ -569,7 +566,6 @@
 DVLR Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: Received Event 
SUBSCR_CONN_E_ACCEPTED
 DVLR Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_PAGING_RESP
 DVLR Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: state_chg to 
SUBSCR_CONN_S_ACCEPTED
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
 DREF VLR subscr MSISDN:46071 usage increases to: 6
 DREF MSISDN:46071: MSC conn use + 1 == 3
 - DTAP --> MS: 
09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
diff --git a/tests/msc_vlr/msc_vlr_test_reject_concurrency.err 
b/tests/msc_vlr/msc_vlr_test_reject_concurrency.err
index 874cf5f..ff248e7 100644
--- a/tests/msc_vlr/msc_vlr_test_reject_concurrency.err
+++ b/tests/msc_vlr/msc_vlr_test_reject_concurrency.err
@@ -1188,9 +1188,8 @@
   llist_count(&vsub->cs.requests) == 0
 DREF VLR subscr MSISDN:46071 usage increases to: 3
 DMM Subscriber MSISDN:46071 not paged yet.
-  BTS/BSC sends out paging request to IMSI:901700000004620 for channel type 1
-  strcmp(paging_expecting_imsi, sub->imsi) == 0
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
+  BTS/BSC sends out paging request to MSISDN:46071
+  strcmp(paging_expecting_imsi, vsub->imsi) == 0
 DREF VLR subscr MSISDN:46071 usage increases to: 4
   llist_count(&vsub->cs.requests) == 1
 DREF VLR subscr MSISDN:46071 usage decreases to: 3
@@ -1225,7 +1224,6 @@
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event 
SUBSCR_CONN_E_ACCEPTED
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: 
SUBSCR_CONN_FROM_PAGING_RESP
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to 
SUBSCR_CONN_S_ACCEPTED
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
 DREF VLR subscr MSISDN:46071 usage increases to: 6
 DREF MSISDN:46071: MSC conn use + 1 == 3
 - DTAP --> MS: 
09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
@@ -1403,9 +1401,8 @@
   llist_count(&vsub->cs.requests) == 0
 DREF VLR subscr MSISDN:46071 usage increases to: 3
 DMM Subscriber MSISDN:46071 not paged yet.
-  BTS/BSC sends out paging request to IMSI:901700000004620 for channel type 1
-  strcmp(paging_expecting_imsi, sub->imsi) == 0
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
+  BTS/BSC sends out paging request to MSISDN:46071
+  strcmp(paging_expecting_imsi, vsub->imsi) == 0
 DREF VLR subscr MSISDN:46071 usage increases to: 4
   llist_count(&vsub->cs.requests) == 1
 DREF VLR subscr MSISDN:46071 usage decreases to: 3
@@ -1440,7 +1437,6 @@
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event 
SUBSCR_CONN_E_ACCEPTED
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: 
SUBSCR_CONN_FROM_PAGING_RESP
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to 
SUBSCR_CONN_S_ACCEPTED
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
 DREF VLR subscr MSISDN:46071 usage increases to: 6
 DREF MSISDN:46071: MSC conn use + 1 == 3
 - DTAP --> MS: 
09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
@@ -1635,9 +1631,8 @@
   llist_count(&vsub->cs.requests) == 0
 DREF VLR subscr MSISDN:46071 usage increases to: 3
 DMM Subscriber MSISDN:46071 not paged yet.
-  BTS/BSC sends out paging request to IMSI:901700000004620 for channel type 1
-  strcmp(paging_expecting_imsi, sub->imsi) == 0
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
+  BTS/BSC sends out paging request to MSISDN:46071
+  strcmp(paging_expecting_imsi, vsub->imsi) == 0
 DREF VLR subscr MSISDN:46071 usage increases to: 4
   llist_count(&vsub->cs.requests) == 1
 DREF VLR subscr MSISDN:46071 usage decreases to: 3
@@ -1672,7 +1667,6 @@
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event 
SUBSCR_CONN_E_ACCEPTED
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: 
SUBSCR_CONN_FROM_PAGING_RESP
 DVLR Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to 
SUBSCR_CONN_S_ACCEPTED
-DREF BSC subscr IMSI:901700000004620 usage decreases to: 0
 DREF VLR subscr MSISDN:46071 usage increases to: 6
 DREF MSISDN:46071: MSC conn use + 1 == 3
 - DTAP --> MS: 
09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
diff --git a/tests/msc_vlr/msc_vlr_test_umts_authen.err 
b/tests/msc_vlr/msc_vlr_test_umts_authen.err
index 67c69c0..84d09ae 100644
--- a/tests/msc_vlr/msc_vlr_test_umts_authen.err
+++ b/tests/msc_vlr/msc_vlr_test_umts_authen.err
@@ -253,9 +253,8 @@
   llist_count(&vsub->cs.requests) == 0
 DREF VLR subscr MSISDN:42342 usage increases to: 3
 DMM Subscriber MSISDN:42342 not paged yet.
-  BTS/BSC sends out paging request to IMSI:901700000010650 for channel type 1
-  strcmp(paging_expecting_imsi, sub->imsi) == 0
-DREF BSC subscr IMSI:901700000010650 usage decreases to: 0
+  BTS/BSC sends out paging request to MSISDN:42342
+  strcmp(paging_expecting_imsi, vsub->imsi) == 0
 DREF VLR subscr MSISDN:42342 usage increases to: 4
   llist_count(&vsub->cs.requests) == 1
 DREF VLR subscr MSISDN:42342 usage decreases to: 3
@@ -335,7 +334,6 @@
 DVLR Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: Received Event 
SUBSCR_CONN_E_ACCEPTED
 DVLR Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: 
SUBSCR_CONN_FROM_PAGING_RESP
 DVLR Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: state_chg to 
SUBSCR_CONN_S_ACCEPTED
-DREF BSC subscr IMSI:901700000010650 usage decreases to: 0
 DREF VLR subscr MSISDN:42342 usage increases to: 5
 DREF MSISDN:42342: MSC conn use + 1 == 3
 - DTAP --> MS: 
09015801000791447758100650004c0005802443f2000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
@@ -665,9 +663,8 @@
   llist_count(&vsub->cs.requests) == 0
 DREF VLR subscr MSISDN:42342 usage increases to: 3
 DMM Subscriber MSISDN:42342 not paged yet.
-  BTS/BSC sends out paging request to IMSI:901700000010650 for channel type 1
-  strcmp(paging_expecting_imsi, sub->imsi) == 0
-DREF BSC subscr IMSI:901700000010650 usage decreases to: 0
+  BTS/BSC sends out paging request to MSISDN:42342
+  strcmp(paging_expecting_imsi, vsub->imsi) == 0
 DREF VLR subscr MSISDN:42342 usage increases to: 4
   llist_count(&vsub->cs.requests) == 1
 DREF VLR subscr MSISDN:42342 usage decreases to: 3
@@ -747,7 +744,6 @@
 DVLR Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: Received Event 
SUBSCR_CONN_E_ACCEPTED
 DVLR Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: 
SUBSCR_CONN_FROM_PAGING_RESP
 DVLR Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: state_chg to 
SUBSCR_CONN_S_ACCEPTED
-DREF BSC subscr IMSI:901700000010650 usage decreases to: 0
 DREF VLR subscr MSISDN:42342 usage increases to: 5
 DREF MSISDN:42342: MSC conn use + 1 == 3
 - DTAP --> MS: 
09015801000791447758100650004c0005802443f2000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
diff --git a/tests/msc_vlr/msc_vlr_tests.c b/tests/msc_vlr/msc_vlr_tests.c
index 8f04593..00196c6 100644
--- a/tests/msc_vlr/msc_vlr_tests.c
+++ b/tests/msc_vlr/msc_vlr_tests.c
@@ -252,33 +252,25 @@
        paging_expecting_imsi = NULL;
 }
 
-/* override, requires '-Wl,--wrap=paging_request' */
-int __real_paging_request(struct gsm_network *network, struct bsc_subscr *sub,
-                         int type, gsm_cbfn *cbfn, void *data);
-int __wrap_paging_request(struct gsm_network *network, struct bsc_subscr *sub,
-                         int type, gsm_cbfn *cbfn, void *data)
+/* override, requires '-Wl,--wrap=msc_fake_paging_request' */
+int __real_msc_fake_paging_request(struct vlr_subscr *vsub);
+int __wrap_msc_fake_paging_request(struct vlr_subscr *vsub)
 {
-       log("BTS/BSC sends out paging request to %s for channel type %d",
-           bsc_subscr_name(sub), type);
+       log("BTS/BSC sends out paging request to %s",
+           vlr_subscr_name(vsub));
        OSMO_ASSERT(paging_expecting_imsi || (paging_expecting_tmsi != 
GSM_RESERVED_TMSI));
        if (paging_expecting_imsi)
-               VERBOSE_ASSERT(strcmp(paging_expecting_imsi, sub->imsi), == 0, 
"%d");
+               VERBOSE_ASSERT(strcmp(paging_expecting_imsi, vsub->imsi), == 0, 
"%d");
        if (paging_expecting_tmsi != GSM_RESERVED_TMSI)
-               VERBOSE_ASSERT(paging_expecting_tmsi, == sub->tmsi, "0x%08x");
+               VERBOSE_ASSERT(paging_expecting_tmsi, == vsub->tmsi, "0x%08x");
        paging_sent = true;
        paging_stopped = false;
        return 1;
 }
 
-/* override, requires '-Wl,--wrap=paging_request_stop' */
-void __real_paging_request_stop(struct gsm_bts *_bts,
-                               struct vlr_subscr *vsub,
-                               struct gsm_subscriber_connection *conn,
-                               struct msgb *msg);
-void __wrap_paging_request_stop(struct gsm_bts *_bts,
-                               struct vlr_subscr *vsub,
-                               struct gsm_subscriber_connection *conn,
-                               struct msgb *msg)
+/* override, requires '-Wl,--wrap=msc_fake_paging_request_stop' */
+void __real_msc_fake_paging_request_stop(struct vlr_subscr *vsub);
+void __wrap_msc_fake_paging_request_stop(struct vlr_subscr *vsub)
 {
        paging_stopped = true;
 }

-- 
To view, visit https://gerrit.osmocom.org/3345
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: Id3705236350d5f69e447046b0a764bbabc3d493c
Gerrit-PatchSet: 2
Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Owner: Neels Hofmeyr <[email protected]>
Gerrit-Reviewer: Jenkins Builder

Reply via email to