From c121bb3188445dfc23a6daef3444031f447395bb Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 26 Dec 2012 10:17:42 +0100 Subject: handover: Fix the handover signalling for IP based BTSes This was reported by Kevin when he was testing handover. The problem is the order of the signal handlers for S_ABISIP_CRCX_ACK. Right now the handover signal handler is called before the one inside the libmsc gsm_04_08.c. This means S_HANDOVER_ACK is signalled _before_ there is a rtp socket created for the channel. The result is that the MDCX will never be sent and the called will not be properly switched _after_ the handover detection. I do not want to play with the order of signal handlers, remove the CRCX ack handling from the handover_logic.c and force the NITB (and later the BSC) to check if the lchan is involved with a handover and do the switching in there. This means right now we do what two signal handlers did in one. Reproduced and tested with the FakeBTS Handover test. Log message: <0004> abis_rsl.c:1954 (bts=1,trx=0,ts=3,ss=0) IPAC_CRCX_ACK ... <000c> gsm_04_08.c:1400 no RTP socket for new_lchan <001a> rtp_proxy.c:533 rtp_socket_create(): success <001a> rtp_proxy.c:615 rtp_socket_bind(rs=0x48703c8, IP=0.0.0.0): ... --- openbsc/include/openbsc/handover.h | 3 +++ openbsc/include/openbsc/signal.h | 10 ---------- openbsc/src/libbsc/handover_logic.c | 35 +++++++++-------------------------- openbsc/src/libmsc/gsm_04_08.c | 33 ++++++++++++++++++++------------- openbsc/src/osmo-bsc/osmo_bsc_audio.c | 4 ++++ 5 files changed, 36 insertions(+), 49 deletions(-) diff --git a/openbsc/include/openbsc/handover.h b/openbsc/include/openbsc/handover.h index 9d9a90b84..bd0d8ad6c 100644 --- a/openbsc/include/openbsc/handover.h +++ b/openbsc/include/openbsc/handover.h @@ -11,4 +11,7 @@ int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts); /* clear any operation for this connection */ void bsc_clear_handover(struct gsm_subscriber_connection *conn, int free_lchan); +/* Return the old lchan or NULL. This is meant for audio handling */ +struct gsm_lchan *bsc_handover_pending(struct gsm_lchan *new_lchan); + #endif /* _HANDOVER_H */ diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h index 598d470f5..fd13ac719 100644 --- a/openbsc/include/openbsc/signal.h +++ b/openbsc/include/openbsc/signal.h @@ -226,16 +226,6 @@ struct msc_signal_data { struct osmo_msc_data *data; }; -/* handover */ -enum signal_ho { - S_HANDOVER_ACK, -}; - -struct ho_signal_data { - struct gsm_lchan *old_lchan; - struct gsm_lchan *new_lchan; -}; - /* SS_CCCH signals */ enum signal_ccch { S_CCCH_PAGING_LOAD, diff --git a/openbsc/src/libbsc/handover_logic.c b/openbsc/src/libbsc/handover_logic.c index d2cd5efd9..9cf26af9d 100644 --- a/openbsc/src/libbsc/handover_logic.c +++ b/openbsc/src/libbsc/handover_logic.c @@ -329,23 +329,6 @@ static int ho_rsl_detect(struct gsm_lchan *new_lchan) return 0; } -static int ho_ipac_crcx_ack(struct gsm_lchan *new_lchan) -{ - struct bsc_handover *ho; - struct ho_signal_data sig_ho; - - ho = bsc_ho_by_new_lchan(new_lchan); - if (!ho) { - /* it is perfectly normal, we have CRCX even in non-HO cases */ - return 0; - } - - sig_ho.old_lchan = ho->old_lchan; - sig_ho.new_lchan = new_lchan; - osmo_signal_dispatch(SS_HO, S_HANDOVER_ACK, &sig_ho); - return 0; -} - static int ho_logic_sig_cb(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data) { @@ -369,14 +352,6 @@ static int ho_logic_sig_cb(unsigned int subsys, unsigned int signal, return ho_gsm48_ho_fail(lchan); } break; - case SS_ABISIP: - lchan = signal_data; - switch (signal) { - case S_ABISIP_CRCX_ACK: - return ho_ipac_crcx_ack(lchan); - break; - } - break; default: break; } @@ -384,8 +359,16 @@ static int ho_logic_sig_cb(unsigned int subsys, unsigned int signal, return 0; } +struct gsm_lchan *bsc_handover_pending(struct gsm_lchan *new_lchan) +{ + struct bsc_handover *ho; + ho = bsc_ho_by_new_lchan(new_lchan); + if (!ho) + return NULL; + return ho->old_lchan; +} + static __attribute__((constructor)) void on_dso_load_ho_logic(void) { osmo_signal_register_handler(SS_LCHAN, ho_logic_sig_cb, NULL); - osmo_signal_register_handler(SS_ABISIP, ho_logic_sig_cb, NULL); } diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index d1dfa4a72..65e6fcc99 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -2,7 +2,7 @@ * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */ /* (C) 2008-2009 by Harald Welte - * (C) 2008-2010 by Holger Hans Peter Freyther + * (C) 2008-2012 by Holger Hans Peter Freyther * * All Rights Reserved * @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -1378,14 +1379,10 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable); /* handle audio path for handover */ -static int handle_ho_signal(unsigned int subsys, unsigned int signal, - void *handler_data, void *signal_data) +static int switch_for_handover(struct gsm_lchan *old_lchan, + struct gsm_lchan *new_lchan) { struct rtp_socket *old_rs, *new_rs, *other_rs; - struct ho_signal_data *sig = signal_data; - - if (subsys != SS_HO || signal != S_HANDOVER_ACK) - return 0; if (ipacc_rtp_direct) { LOGP(DHO, LOGL_ERROR, "unable to handover in direct RTP mode\n"); @@ -1393,15 +1390,15 @@ static int handle_ho_signal(unsigned int subsys, unsigned int signal, } /* RTP Proxy mode */ - new_rs = sig->new_lchan->abis_ip.rtp_socket; - old_rs = sig->old_lchan->abis_ip.rtp_socket; + 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(sig->new_lchan); + rsl_ipacc_mdcx_to_rtpsock(new_lchan); if (!old_rs) { LOGP(DHO, LOGL_ERROR, "no RTP socket for old_lchan\n"); @@ -1413,7 +1410,7 @@ static int handle_ho_signal(unsigned int subsys, unsigned int signal, new_rs->tx_action = old_rs->tx_action; new_rs->transmit = old_rs->transmit; - switch (sig->old_lchan->abis_ip.rtp_socket->rx_action) { + 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); @@ -1435,7 +1432,7 @@ static int handle_ho_signal(unsigned int subsys, unsigned int signal, static int handle_abisip_signal(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data) { - struct gsm_lchan *lchan = signal_data; + struct gsm_lchan *lchan = signal_data, *old_lchan; int rc; struct gsm_network *net; struct gsm_trans *trans; @@ -1476,6 +1473,17 @@ static int handle_abisip_signal(unsigned int subsys, unsigned int signal, 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. + */ + old_lchan = bsc_handover_pending(lchan); + if (old_lchan) + switch_for_handover(old_lchan, lchan); break; case S_ABISIP_DLCX_IND: /* the BTS tells us a RTP stream has been disconnected */ @@ -3253,6 +3261,5 @@ int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg) */ static __attribute__((constructor)) void on_dso_load_0408(void) { - osmo_signal_register_handler(SS_HO, handle_ho_signal, NULL); osmo_signal_register_handler(SS_ABISIP, handle_abisip_signal, NULL); } diff --git a/openbsc/src/osmo-bsc/osmo_bsc_audio.c b/openbsc/src/osmo-bsc/osmo_bsc_audio.c index ed0ece761..660d88497 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_audio.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_audio.c @@ -45,6 +45,10 @@ static int handle_abisip_signal(unsigned int subsys, unsigned int signal, switch (signal) { case S_ABISIP_CRCX_ACK: + /* + * TODO: handle handover here... then the audio should go to + * the old mgcp port.. + */ /* we can ask it to connect now */ LOGP(DMSC, LOGL_DEBUG, "Connecting BTS to port: %d conn: %d\n", con->sccp_con->rtp_port, lchan->abis_ip.conn_id); -- cgit v1.2.3