diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 7c3ca8497..41fe3281f 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -382,6 +382,20 @@ static inline int is_nokia_bts(struct gsm_bts *bts) return 0; } +static inline int is_e1_bts(struct gsm_bts *bts) +{ + switch (bts->type) { + case GSM_BTS_TYPE_BS11: + case GSM_BTS_TYPE_RBS2000: + case GSM_BTS_TYPE_NOKIA_SITE: + return 1; + default: + break; + } + + return 0; +} + enum gsm_auth_policy gsm_auth_policy_parse(const char *arg); const char *gsm_auth_policy_name(enum gsm_auth_policy policy); diff --git a/openbsc/include/openbsc/trau_mux.h b/openbsc/include/openbsc/trau_mux.h index 3de50f772..d211d8d74 100644 --- a/openbsc/include/openbsc/trau_mux.h +++ b/openbsc/include/openbsc/trau_mux.h @@ -51,6 +51,9 @@ int trau_recv_lchan(struct gsm_lchan *lchan, uint32_t callref); /* send trau from application */ int trau_send_frame(struct gsm_lchan *lchan, struct gsm_data_frame *frame); +/* switch trau muxer to new lchan */ +int switch_trau_mux(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan); + /* callback invoked if we receive TRAU frames */ int subch_cb(struct subch_demux *dmx, int ch, uint8_t *data, int len, void *_priv); diff --git a/openbsc/src/libbsc/bsc_api.c b/openbsc/src/libbsc/bsc_api.c index 86d249376..e56703837 100644 --- a/openbsc/src/libbsc/bsc_api.c +++ b/openbsc/src/libbsc/bsc_api.c @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -419,6 +420,10 @@ static void handle_ass_compl(struct gsm_subscriber_connection *conn, return; } + /* switch TRAU muxer for E1 based BTS from one channel to another */ + if (is_e1_bts(conn->bts)) + switch_trau_mux(conn->lchan, conn->secondary_lchan); + /* swap channels */ osmo_timer_del(&conn->T10); diff --git a/openbsc/src/libbsc/handover_logic.c b/openbsc/src/libbsc/handover_logic.c index 9cf26af9d..36a758be6 100644 --- a/openbsc/src/libbsc/handover_logic.c +++ b/openbsc/src/libbsc/handover_logic.c @@ -39,6 +39,7 @@ #include #include #include +#include struct bsc_handover { struct llist_head list; @@ -264,6 +265,10 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan) osmo_timer_del(&ho->T3103); + /* switch TRAU muxer for E1 based BTS from one channel to another */ + if (is_e1_bts(new_lchan->conn->bts)) + switch_trau_mux(ho->old_lchan, new_lchan); + /* Replace the ho lchan with the primary one */ if (ho->old_lchan != new_lchan->conn->lchan) LOGP(DHO, LOGL_ERROR, "Primary lchan changed during handover.\n"); @@ -278,8 +283,6 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan) rsl_lchan_set_state(ho->old_lchan, LCHAN_S_INACTIVE); lchan_release(ho->old_lchan, 0, RSL_REL_LOCAL_END); - /* do something to re-route the actual speech frames ! */ - llist_del(&ho->list); talloc_free(ho); diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index 0c6b100a6..bc4a9c31b 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -1648,6 +1648,9 @@ static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable) 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_OSMO_SYSMO: @@ -1655,10 +1658,12 @@ static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable) LOGP(DCC, LOGL_ERROR, "Error: RTP proxy is disabled\n"); return -EINVAL; } - /* in case, we don't have a RTP socket yet, we note this - * in the transaction and try later */ + /* 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) { - trans->tch_recv = enable; DEBUGP(DCC, "queue tch_recv_mncc request (%d)\n", enable); return 0; } @@ -1677,6 +1682,14 @@ static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable) 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); diff --git a/openbsc/src/libtrau/trau_mux.c b/openbsc/src/libtrau/trau_mux.c index c9d77cf78..7b9bac0eb 100644 --- a/openbsc/src/libtrau/trau_mux.c +++ b/openbsc/src/libtrau/trau_mux.c @@ -31,6 +31,7 @@ #include #include #include +#include /* this corresponds to the bit-lengths of the individual codec * parameters as indicated in Table 1.1 of TS 06.10 */ @@ -518,3 +519,20 @@ int trau_send_frame(struct gsm_lchan *lchan, struct gsm_data_frame *frame) return subchan_mux_enqueue(mx, dst_e1_ss->e1_ts_ss, trau_bits_out, TRAU_FRAME_BITS); } + +/* switch trau muxer to new lchan */ +int switch_trau_mux(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan) +{ + struct gsm_network *net = old_lchan->ts->trx->bts->network; + struct gsm_trans *trans; + + /* look up transaction with TCH frame receive enabled */ + llist_for_each_entry(trans, &net->trans_list, entry) { + if (trans->conn && trans->conn->lchan == old_lchan && trans->tch_recv) { + /* switch */ + trau_recv_lchan(new_lchan, trans->callref); + } + } + + return 0; +}